MM-14412: Enables force removals of team/channel members base on group constraints. (#10490)
* MM-14412: Enables force removals of team/channel members base on group constraints. * Renames some existing methods and variables. * Change return types to ChannelMembers and TeamMembers for some existing methods. * Adds option to change LDAP_DATA to either 'qa' or 'test' with env variable. * Adds methods to retrieve ChannelMembers and TeamMembers that, based on group constraints, should be deleted. * Adds helper functions to create GroupTeams and GroupChannels. * MM-14412: Switches to helper methods for GroupSyncable creation in test files. * MM-14412: Style fix. * MM-14412: Switches remaining GroupSyncable instances to be created with helper functions. * MM-14412: Typo fix. * MM-11412: Build fixes. * MM-14412: Checks if user is team member before re-adding. * MM-14412: Update for change of GroupConstrained fields type.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cee65379c7
Коммит
25fd962016
7
Makefile
7
Makefile
@@ -16,6 +16,7 @@ BUILD_ENTERPRISE ?= true
|
||||
BUILD_ENTERPRISE_READY = false
|
||||
BUILD_TYPE_NAME = team
|
||||
BUILD_HASH_ENTERPRISE = none
|
||||
LDAP_DATA ?= test
|
||||
ifneq ($(wildcard $(BUILD_ENTERPRISE_DIR)/.),)
|
||||
ifeq ($(BUILD_ENTERPRISE),true)
|
||||
BUILD_ENTERPRISE_READY = true
|
||||
@@ -157,11 +158,9 @@ ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||
-e LDAP_ADMIN_PASSWORD="mostest" \
|
||||
-d osixia/openldap:1.2.2 > /dev/null;\
|
||||
sleep 10; \
|
||||
docker cp tests/add-users.ldif mattermost-openldap:/add-users.ldif;\
|
||||
docker cp tests/add-groups.ldif mattermost-openldap:/add-groups.ldif;\
|
||||
docker cp tests/test-data.ldif mattermost-openldap:/test-data.ldif;\
|
||||
docker cp tests/qa-data.ldif mattermost-openldap:/qa-data.ldif;\
|
||||
docker exec -ti mattermost-openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /add-users.ldif';\
|
||||
docker exec -ti mattermost-openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /add-groups.ldif';\
|
||||
docker exec -ti mattermost-openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /$(LDAP_DATA)-data.ldif';\
|
||||
elif [ $(shell docker ps | grep -ci mattermost-openldap) -eq 0 ]; then \
|
||||
echo restarting mattermost-openldap; \
|
||||
docker start mattermost-openldap > /dev/null; \
|
||||
|
||||
24
app/group.go
24
app/group.go
@@ -133,18 +133,34 @@ func (a *App) DeleteGroupSyncable(groupID string, syncableID string, syncableTyp
|
||||
return result.Data.(*model.GroupSyncable), nil
|
||||
}
|
||||
|
||||
func (a *App) PendingAutoAddTeamMembers(minGroupMembersCreateAt int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().PendingAutoAddTeamMembers(minGroupMembersCreateAt)
|
||||
func (a *App) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().TeamMembersToAdd(since)
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
return result.Data.([]*model.UserTeamIDPair), nil
|
||||
}
|
||||
|
||||
func (a *App) PendingAutoAddChannelMembers(minGroupMembersCreateAt int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().PendingAutoAddChannelMembers(minGroupMembersCreateAt)
|
||||
func (a *App) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().ChannelMembersToAdd(since)
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
return result.Data.([]*model.UserChannelIDPair), nil
|
||||
}
|
||||
|
||||
func (a *App) TeamMembersToRemove() ([]*model.TeamMember, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().TeamMembersToRemove()
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
return result.Data.([]*model.TeamMember), nil
|
||||
}
|
||||
|
||||
func (a *App) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError) {
|
||||
result := <-a.Srv.Store.Group().ChannelMembersToRemove()
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
return result.Data.([]*model.ChannelMember), nil
|
||||
}
|
||||
|
||||
@@ -135,12 +135,7 @@ func TestCreateGroupSyncable(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
group := th.CreateGroup()
|
||||
groupSyncable := &model.GroupSyncable{
|
||||
GroupId: group.Id,
|
||||
AutoAdd: false,
|
||||
SyncableId: th.BasicTeam.Id,
|
||||
Type: model.GroupSyncableTypeTeam,
|
||||
}
|
||||
groupSyncable := model.NewGroupTeam(group.Id, th.BasicTeam.Id, false)
|
||||
|
||||
gs, err := th.App.CreateGroupSyncable(groupSyncable)
|
||||
require.Nil(t, err)
|
||||
@@ -155,12 +150,7 @@ func TestGetGroupSyncable(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
group := th.CreateGroup()
|
||||
groupSyncable := &model.GroupSyncable{
|
||||
GroupId: group.Id,
|
||||
AutoAdd: false,
|
||||
SyncableId: th.BasicTeam.Id,
|
||||
Type: model.GroupSyncableTypeTeam,
|
||||
}
|
||||
groupSyncable := model.NewGroupTeam(group.Id, th.BasicTeam.Id, false)
|
||||
|
||||
gs, err := th.App.CreateGroupSyncable(groupSyncable)
|
||||
require.Nil(t, err)
|
||||
@@ -177,12 +167,7 @@ func TestGetGroupSyncables(t *testing.T) {
|
||||
group := th.CreateGroup()
|
||||
|
||||
// Create a group team
|
||||
groupSyncable := &model.GroupSyncable{
|
||||
GroupId: group.Id,
|
||||
AutoAdd: false,
|
||||
SyncableId: th.BasicTeam.Id,
|
||||
Type: model.GroupSyncableTypeTeam,
|
||||
}
|
||||
groupSyncable := model.NewGroupTeam(group.Id, th.BasicTeam.Id, false)
|
||||
|
||||
gs, err := th.App.CreateGroupSyncable(groupSyncable)
|
||||
require.Nil(t, err)
|
||||
@@ -198,12 +183,7 @@ func TestDeleteGroupSyncable(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
group := th.CreateGroup()
|
||||
groupChannel := &model.GroupSyncable{
|
||||
GroupId: group.Id,
|
||||
AutoAdd: false,
|
||||
SyncableId: th.BasicChannel.Id,
|
||||
Type: model.GroupSyncableTypeChannel,
|
||||
}
|
||||
groupChannel := model.NewGroupChannel(group.Id, th.BasicChannel.Id, false)
|
||||
|
||||
gs, err := th.App.CreateGroupSyncable(groupChannel)
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
"github.com/mattermost/mattermost-server/mlog"
|
||||
)
|
||||
|
||||
// PopulateSyncablesSince adds users to teams and channels based on their group memberships and how those groups are
|
||||
// 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) PopulateSyncablesSince(groupMembersCreatedAfter int64) error {
|
||||
userTeamIDs, appErr := a.PendingAutoAddTeamMembers(groupMembersCreatedAfter)
|
||||
func (a *App) CreateDefaultMemberships(since int64) error {
|
||||
teamMembers, appErr := a.TeamMembersToAdd(since)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userTeam := range userTeamIDs {
|
||||
for _, userTeam := range teamMembers {
|
||||
_, err := a.AddTeamMember(userTeam.TeamID, userTeam.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -27,26 +27,33 @@ func (a *App) PopulateSyncablesSince(groupMembersCreatedAfter int64) error {
|
||||
)
|
||||
}
|
||||
|
||||
userChannelIDs, appErr := a.PendingAutoAddChannelMembers(groupMembersCreatedAfter)
|
||||
channelMembers, appErr := a.ChannelMembersToAdd(since)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userChannel := range userChannelIDs {
|
||||
for _, userChannel := range channelMembers {
|
||||
channel, err := a.GetChannel(userChannel.ChannelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// First add user to team
|
||||
_, err = a.AddTeamMember(channel.TeamId, userChannel.UserID)
|
||||
if err != nil {
|
||||
tmem, err := a.GetTeamMember(channel.TeamId, userChannel.UserID)
|
||||
if err != nil && err.Id != "store.sql_team.get_member.missing.app_error" {
|
||||
return err
|
||||
}
|
||||
a.Log.Info("added teammember",
|
||||
mlog.String("user_id", userChannel.UserID),
|
||||
mlog.String("team_id", channel.TeamId),
|
||||
)
|
||||
|
||||
// First add user to team
|
||||
if tmem == nil {
|
||||
_, err = a.AddTeamMember(channel.TeamId, userChannel.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Log.Info("added teammember",
|
||||
mlog.String("user_id", userChannel.UserID),
|
||||
mlog.String("team_id", channel.TeamId),
|
||||
)
|
||||
}
|
||||
|
||||
_, err = a.AddChannelMember(userChannel.UserID, channel, "", "", "")
|
||||
if err != nil {
|
||||
@@ -61,3 +68,48 @@ func (a *App) PopulateSyncablesSince(groupMembersCreatedAfter int64) error {
|
||||
|
||||
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()
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userChannel := range channelMembers {
|
||||
channel, err := a.GetChannel(userChannel.ChannelId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = a.RemoveUserFromChannel(userChannel.UserId, "", channel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Log.Info("removed channelmember",
|
||||
mlog.String("user_id", userChannel.UserId),
|
||||
mlog.String("channel_id", channel.Id),
|
||||
)
|
||||
}
|
||||
|
||||
teamMembers, appErr := a.TeamMembersToRemove()
|
||||
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
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPopulateSyncablesSince(t *testing.T) {
|
||||
func TestCreateDefaultMemberships(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
@@ -70,32 +71,17 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("test group not created: %s", err.Error())
|
||||
}
|
||||
|
||||
_, err = th.App.CreateGroupSyncable(&model.GroupSyncable{
|
||||
AutoAdd: true,
|
||||
GroupId: gleeGroup.Id,
|
||||
SyncableId: practiceChannel.Id,
|
||||
Type: model.GroupSyncableTypeChannel,
|
||||
})
|
||||
_, err = th.App.CreateGroupSyncable(model.NewGroupChannel(gleeGroup.Id, practiceChannel.Id, true))
|
||||
if err != nil {
|
||||
t.Errorf("test groupchannel not created: %s", err.Error())
|
||||
}
|
||||
|
||||
scienceTeamGroupSyncable, err := th.App.CreateGroupSyncable(&model.GroupSyncable{
|
||||
AutoAdd: false,
|
||||
GroupId: scienceGroup.Id,
|
||||
SyncableId: nerdsTeam.Id,
|
||||
Type: model.GroupSyncableTypeTeam,
|
||||
})
|
||||
scienceTeamGroupSyncable, err := th.App.CreateGroupSyncable(model.NewGroupTeam(scienceGroup.Id, nerdsTeam.Id, false))
|
||||
if err != nil {
|
||||
t.Errorf("test groupteam not created: %s", err.Error())
|
||||
}
|
||||
|
||||
scienceChannelGroupSyncable, err := th.App.CreateGroupSyncable(&model.GroupSyncable{
|
||||
AutoAdd: false,
|
||||
GroupId: scienceGroup.Id,
|
||||
SyncableId: experimentsChannel.Id,
|
||||
Type: model.GroupSyncableTypeChannel,
|
||||
})
|
||||
scienceChannelGroupSyncable, err := th.App.CreateGroupSyncable(model.NewGroupChannel(scienceGroup.Id, experimentsChannel.Id, false))
|
||||
if err != nil {
|
||||
t.Errorf("test groupchannel not created: %s", err.Error())
|
||||
}
|
||||
@@ -113,7 +99,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("test groupmember not created: %s", err.Error())
|
||||
}
|
||||
|
||||
pErr := th.App.PopulateSyncablesSince(0)
|
||||
pErr := th.App.CreateDefaultMemberships(0)
|
||||
if pErr != nil {
|
||||
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -183,7 +169,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
}
|
||||
|
||||
// Sync everything after syncable was created (proving that team updates trigger re-sync)
|
||||
pErr = th.App.PopulateSyncablesSince(scientistGroupMember.CreateAt + 1)
|
||||
pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
|
||||
if pErr != nil {
|
||||
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -226,7 +212,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
}
|
||||
|
||||
// Sync everything after syncable was created (proving that channel updates trigger re-sync)
|
||||
pErr = th.App.PopulateSyncablesSince(scientistGroupMember.CreateAt + 1)
|
||||
pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
|
||||
if pErr != nil {
|
||||
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -251,7 +237,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
}
|
||||
|
||||
// Even re-syncing from the beginning doesn't re-add to channel or team
|
||||
pErr = th.App.PopulateSyncablesSince(0)
|
||||
pErr = th.App.CreateDefaultMemberships(0)
|
||||
if pErr != nil {
|
||||
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -292,7 +278,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("error updating group syncable: %s", err.Error())
|
||||
}
|
||||
|
||||
pErr = th.App.PopulateSyncablesSince(0)
|
||||
pErr = th.App.CreateDefaultMemberships(0)
|
||||
if pErr != nil {
|
||||
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -313,7 +299,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error())
|
||||
}
|
||||
|
||||
pErr = th.App.PopulateSyncablesSince(scienceChannelGroupSyncable.UpdateAt)
|
||||
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
|
||||
if pErr != nil {
|
||||
t.Errorf("failed to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -329,7 +315,7 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error())
|
||||
}
|
||||
|
||||
pErr = th.App.PopulateSyncablesSince(scienceChannelGroupSyncable.UpdateAt)
|
||||
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
|
||||
if pErr != nil {
|
||||
t.Errorf("failed to populate syncables: %s", pErr.Error())
|
||||
}
|
||||
@@ -340,3 +326,70 @@ func TestPopulateSyncablesSince(t *testing.T) {
|
||||
t.Errorf("expected channel member: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteGroupMemberships(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
group := th.CreateGroup()
|
||||
|
||||
userIDs := []string{th.BasicUser.Id, th.BasicUser2.Id, th.SystemAdminUser.Id}
|
||||
|
||||
var err *model.AppError
|
||||
// add users to teams and channels
|
||||
for _, userID := range userIDs {
|
||||
_, err = th.App.AddTeamMember(th.BasicTeam.Id, userID)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = th.App.AddChannelMember(userID, th.BasicChannel, "", "", "")
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
// make team group-constrained
|
||||
team := th.BasicTeam
|
||||
team.GroupConstrained = model.NewBool(true)
|
||||
team, err = th.App.UpdateTeam(team)
|
||||
require.Nil(t, err)
|
||||
require.True(t, *team.GroupConstrained)
|
||||
|
||||
// make channel group-constrained
|
||||
channel := th.BasicChannel
|
||||
channel.GroupConstrained = model.NewBool(true)
|
||||
channel, err = th.App.UpdateChannel(channel)
|
||||
require.Nil(t, err)
|
||||
require.True(t, *channel.GroupConstrained)
|
||||
|
||||
// create groupteam and groupchannel
|
||||
_, err = th.App.CreateGroupSyncable(model.NewGroupTeam(group.Id, team.Id, true))
|
||||
require.Nil(t, err)
|
||||
_, err = th.App.CreateGroupSyncable(model.NewGroupChannel(group.Id, channel.Id, true))
|
||||
require.Nil(t, err)
|
||||
|
||||
// verify the member count
|
||||
tmembers, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, tmembers, 3)
|
||||
|
||||
cmemberCount, err := th.App.GetChannelMemberCount(th.BasicChannel.Id)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 3, int(cmemberCount))
|
||||
|
||||
// add a user to the group
|
||||
_, err = th.App.CreateOrRestoreGroupMember(group.Id, th.SystemAdminUser.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
// run the delete
|
||||
appErr := th.App.DeleteGroupConstrainedMemberships()
|
||||
require.Nil(t, appErr)
|
||||
|
||||
// verify the new member counts
|
||||
tmembers, err = th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, tmembers, 1)
|
||||
require.Equal(t, th.SystemAdminUser.Id, tmembers[0].UserId)
|
||||
|
||||
cmembers, err := th.App.GetChannelMembersPage(channel.Id, 0, 99)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, (*cmembers), 1)
|
||||
require.Equal(t, th.SystemAdminUser.Id, (*cmembers)[0].UserId)
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
|
||||
oldTeam.CompanyName = team.CompanyName
|
||||
oldTeam.AllowedDomains = team.AllowedDomains
|
||||
oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate
|
||||
oldTeam.GroupConstrained = team.GroupConstrained
|
||||
|
||||
oldTeam, err = a.updateTeamUnsanitized(oldTeam)
|
||||
if err != nil {
|
||||
|
||||
@@ -108,6 +108,7 @@ pipeline {
|
||||
MM_EMAILSETTINGS_SMTPSERVER = "inbucket"
|
||||
MM_EMAILSETTINGS_SMTPPORT = "10025"
|
||||
MM_ELASTICSEARCHSETTINGS_CONNECTIONURL = "http://elasticsearch:9200"
|
||||
LDAP_DATA = "test"
|
||||
}
|
||||
|
||||
steps {
|
||||
@@ -116,8 +117,7 @@ pipeline {
|
||||
sh """
|
||||
docker-compose --no-ansi run --rm start_dependencies
|
||||
docker-compose --no-ansi ps
|
||||
docker-compose --no-ansi exec -T openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /add-users.ldif';
|
||||
docker-compose --no-ansi exec -T openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /add-groups.ldif';
|
||||
docker-compose --no-ansi exec -T openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest -f /${LDAP_DATA}-data.ldif';
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ services:
|
||||
LDAP_DOMAIN: "mm.test.com"
|
||||
LDAP_ADMIN_PASSWORD: "mostest"
|
||||
volumes:
|
||||
- "../tests/add-users.ldif:/add-users.ldif"
|
||||
- "../tests/add-groups.ldif:/add-groups.ldif"
|
||||
- "../tests/test-data.ldif:/test-data.ldif"
|
||||
- "../tests/qa-data.ldif:/qa-data.ldif"
|
||||
elasticsearch:
|
||||
image: "mattermost/mattermost-elasticsearch-docker:6.5.1"
|
||||
networks:
|
||||
|
||||
@@ -6982,6 +6982,10 @@
|
||||
"id": "ent.ldap.syncronize.populate_syncables",
|
||||
"translation": "error populating syncables"
|
||||
},
|
||||
{
|
||||
"id": "ent.ldap.syncronize.delete_group_constained_memberships",
|
||||
"translation": "error deleting team or channel memberships"
|
||||
},
|
||||
{
|
||||
"id": "model.group.create_at.app_error",
|
||||
"translation": "invalid create at property for group"
|
||||
|
||||
@@ -155,3 +155,21 @@ func GroupSyncablesFromJson(data io.Reader) []*GroupSyncable {
|
||||
json.Unmarshal(bodyBytes, &groupSyncables)
|
||||
return groupSyncables
|
||||
}
|
||||
|
||||
func NewGroupTeam(groupID, teamID string, autoAdd bool) *GroupSyncable {
|
||||
return &GroupSyncable{
|
||||
GroupId: groupID,
|
||||
SyncableId: teamID,
|
||||
Type: GroupSyncableTypeTeam,
|
||||
AutoAdd: autoAdd,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGroupChannel(groupID, channelID string, autoAdd bool) *GroupSyncable {
|
||||
return &GroupSyncable{
|
||||
GroupId: groupID,
|
||||
SyncableId: channelID,
|
||||
Type: GroupSyncableTypeChannel,
|
||||
AutoAdd: autoAdd,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,14 +454,26 @@ func (s *LayeredGroupStore) DeleteGroupSyncable(groupID string, syncableID strin
|
||||
})
|
||||
}
|
||||
|
||||
func (s *LayeredGroupStore) PendingAutoAddTeamMembers(minGroupMembersCreateAt int64) StoreChannel {
|
||||
func (s *LayeredGroupStore) TeamMembersToAdd(since int64) StoreChannel {
|
||||
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
|
||||
return supplier.PendingAutoAddTeamMembers(s.TmpContext, minGroupMembersCreateAt)
|
||||
return supplier.TeamMembersToAdd(s.TmpContext, since)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *LayeredGroupStore) PendingAutoAddChannelMembers(minGroupMembersCreateAt int64) StoreChannel {
|
||||
func (s *LayeredGroupStore) ChannelMembersToAdd(since int64) StoreChannel {
|
||||
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
|
||||
return supplier.PendingAutoAddChannelMembers(s.TmpContext, minGroupMembersCreateAt)
|
||||
return supplier.ChannelMembersToAdd(s.TmpContext, since)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *LayeredGroupStore) TeamMembersToRemove() StoreChannel {
|
||||
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
|
||||
return supplier.TeamMembersToRemove(s.TmpContext)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *LayeredGroupStore) ChannelMembersToRemove() StoreChannel {
|
||||
return s.RunQuery(func(supplier LayeredStoreSupplier) *LayeredStoreSupplierResult {
|
||||
return supplier.ChannelMembersToRemove(s.TmpContext)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ type LayeredStoreSupplier interface {
|
||||
GroupUpdateGroupSyncable(ctx context.Context, groupSyncable *model.GroupSyncable, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
GroupDeleteGroupSyncable(ctx context.Context, groupID string, syncableID string, syncableType model.GroupSyncableType, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
|
||||
PendingAutoAddTeamMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
PendingAutoAddChannelMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
TeamMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
ChannelMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
|
||||
TeamMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult
|
||||
}
|
||||
|
||||
@@ -93,10 +93,18 @@ func (s *LocalCacheSupplier) GroupDeleteGroupSyncable(ctx context.Context, group
|
||||
return s.Next().GroupDeleteGroupSyncable(ctx, groupID, syncableID, syncableType, hints...)
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) PendingAutoAddTeamMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().PendingAutoAddTeamMembers(ctx, minGroupMembersCreateAt, hints...)
|
||||
func (s *LocalCacheSupplier) TeamMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().TeamMembersToAdd(ctx, since, hints...)
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) PendingAutoAddChannelMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().PendingAutoAddChannelMembers(ctx, minGroupMembersCreateAt, hints...)
|
||||
func (s *LocalCacheSupplier) ChannelMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().ChannelMembersToAdd(ctx, since, hints...)
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) TeamMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().TeamMembersToRemove(ctx, hints...)
|
||||
}
|
||||
|
||||
func (s *LocalCacheSupplier) ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
return s.Next().ChannelMembersToRemove(ctx, hints...)
|
||||
}
|
||||
|
||||
@@ -89,12 +89,22 @@ func (s *RedisSupplier) GroupDeleteGroupSyncable(ctx context.Context, groupID st
|
||||
return s.Next().GroupDeleteGroupSyncable(ctx, groupID, syncableID, syncableType, hints...)
|
||||
}
|
||||
|
||||
func (s *RedisSupplier) PendingAutoAddTeamMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
func (s *RedisSupplier) TeamMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
// TODO: Redis caching.
|
||||
return s.Next().PendingAutoAddTeamMembers(ctx, minGroupMembersCreateAt, hints...)
|
||||
return s.Next().TeamMembersToAdd(ctx, since, hints...)
|
||||
}
|
||||
|
||||
func (s *RedisSupplier) PendingAutoAddChannelMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
func (s *RedisSupplier) ChannelMembersToAdd(ctx context.Context, since int64, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
// TODO: Redis caching.
|
||||
return s.Next().PendingAutoAddChannelMembers(ctx, minGroupMembersCreateAt, hints...)
|
||||
return s.Next().ChannelMembersToAdd(ctx, since, hints...)
|
||||
}
|
||||
|
||||
func (s *RedisSupplier) TeamMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
// TODO: Redis caching.
|
||||
return s.Next().TeamMembersToRemove(ctx, hints...)
|
||||
}
|
||||
|
||||
func (s *RedisSupplier) ChannelMembersToRemove(ctx context.Context, hints ...LayeredStoreHint) *LayeredStoreSupplierResult {
|
||||
// TODO: Redis caching.
|
||||
return s.Next().ChannelMembersToRemove(ctx, hints...)
|
||||
}
|
||||
|
||||
@@ -668,11 +668,11 @@ func (s *SqlSupplier) GroupDeleteGroupSyncable(ctx context.Context, groupID stri
|
||||
return result
|
||||
}
|
||||
|
||||
// PendingAutoAddTeamMembers returns a slice of UserTeamIDPair that need newly created memberships
|
||||
// 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 *SqlSupplier) PendingAutoAddTeamMembers(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
func (s *SqlSupplier) TeamMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
result := store.NewSupplierResult()
|
||||
|
||||
sql := `
|
||||
@@ -698,23 +698,23 @@ func (s *SqlSupplier) PendingAutoAddTeamMembers(ctx context.Context, since int64
|
||||
AND (GroupMembers.CreateAt >= :Since
|
||||
OR GroupTeams.UpdateAt >= :Since)`
|
||||
|
||||
var userTeamIDs []*model.UserTeamIDPair
|
||||
var teamMembers []*model.UserTeamIDPair
|
||||
|
||||
_, err := s.GetMaster().Select(&userTeamIDs, sql, map[string]interface{}{"Since": since})
|
||||
_, err := s.GetReplica().Select(&teamMembers, sql, map[string]interface{}{"Since": since})
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlGroupStore.PendingAutoAddTeamMembers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
result.Err = model.NewAppError("SqlGroupStore.TeamMembersToAdd", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
result.Data = userTeamIDs
|
||||
result.Data = teamMembers
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// PendingAutoAddChannelMembers returns a slice of UserChannelIDPair that need newly created memberships
|
||||
// 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 *SqlSupplier) PendingAutoAddChannelMembers(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
func (s *SqlSupplier) ChannelMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
result := store.NewSupplierResult()
|
||||
|
||||
sql := `
|
||||
@@ -740,14 +740,14 @@ func (s *SqlSupplier) PendingAutoAddChannelMembers(ctx context.Context, since in
|
||||
AND (GroupMembers.CreateAt >= :Since
|
||||
OR GroupChannels.UpdateAt >= :Since)`
|
||||
|
||||
var userChannelIDs []*model.UserChannelIDPair
|
||||
var channelMembers []*model.UserChannelIDPair
|
||||
|
||||
_, err := s.GetMaster().Select(&userChannelIDs, sql, map[string]interface{}{"Since": since})
|
||||
_, err := s.GetReplica().Select(&channelMembers, sql, map[string]interface{}{"Since": since})
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlGroupStore.PendingAutoAddChannelMembers", "store.select_error", nil, "", http.StatusInternalServerError)
|
||||
result.Err = model.NewAppError("SqlGroupStore.ChannelMembersToAdd", "store.select_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
result.Data = userChannelIDs
|
||||
result.Data = channelMembers
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -765,3 +765,92 @@ func groupSyncableToGroupChannel(groupSyncable *model.GroupSyncable) *groupChann
|
||||
ChannelId: groupSyncable.SyncableId,
|
||||
}
|
||||
}
|
||||
|
||||
// TeamMembersToRemove returns all team members that should be removed based on group constraints.
|
||||
func (s *SqlSupplier) TeamMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
result := store.NewSupplierResult()
|
||||
|
||||
sql := `
|
||||
SELECT
|
||||
TeamMembers.*
|
||||
FROM
|
||||
TeamMembers
|
||||
JOIN Teams ON Teams.Id = TeamMembers.TeamId
|
||||
WHERE
|
||||
TeamMembers.DeleteAt = 0
|
||||
AND Teams.DeleteAt = 0
|
||||
AND Teams.GroupConstrained = TRUE
|
||||
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)`
|
||||
|
||||
var teamMembers []*model.TeamMember
|
||||
|
||||
_, err := s.GetReplica().Select(&teamMembers, sql)
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlGroupStore.TeamMembersToRemove", "store.select_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
result.Data = teamMembers
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove returns all channel members that should be removed based on group constraints.
|
||||
func (s *SqlSupplier) ChannelMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
result := store.NewSupplierResult()
|
||||
|
||||
sql := `
|
||||
SELECT
|
||||
ChannelMembers.*
|
||||
FROM
|
||||
ChannelMembers
|
||||
JOIN Channels ON Channels.Id = ChannelMembers.ChannelId
|
||||
WHERE
|
||||
Channels.DeleteAt = 0
|
||||
AND Channels.GroupConstrained = TRUE
|
||||
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)`
|
||||
|
||||
var channelMembers []*model.ChannelMember
|
||||
|
||||
_, err := s.GetReplica().Select(&channelMembers, sql)
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlGroupStore.ChannelMembersToRemove", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
result.Data = channelMembers
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -640,6 +640,9 @@ func UpgradeDatabaseToVersion510(sqlStore SqlStore) {
|
||||
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(4)", "boolean")
|
||||
sqlStore.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(4)", "boolean")
|
||||
|
||||
sqlStore.CreateIndexIfNotExists("idx_groupteams_teamid", "GroupTeams", "TeamId")
|
||||
sqlStore.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
|
||||
|
||||
saveSchemaVersion(sqlStore, VERSION_5_10_0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,8 +580,11 @@ type GroupStore interface {
|
||||
UpdateGroupSyncable(groupSyncable *model.GroupSyncable) StoreChannel
|
||||
DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) StoreChannel
|
||||
|
||||
PendingAutoAddTeamMembers(minGroupMembersCreateAt int64) StoreChannel
|
||||
PendingAutoAddChannelMembers(minGroupMembersCreateAt int64) StoreChannel
|
||||
TeamMembersToAdd(since int64) StoreChannel
|
||||
ChannelMembersToAdd(since int64) StoreChannel
|
||||
|
||||
TeamMembersToRemove() StoreChannel
|
||||
ChannelMembersToRemove() StoreChannel
|
||||
}
|
||||
|
||||
type LinkMetadataStore interface {
|
||||
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -237,13 +237,13 @@ func (_m *GroupStore) GetMemberUsersPage(groupID string, offset int, limit int)
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddChannelMembers provides a mock function with given fields: minGroupMembersCreateAt
|
||||
func (_m *GroupStore) PendingAutoAddChannelMembers(minGroupMembersCreateAt int64) store.StoreChannel {
|
||||
ret := _m.Called(minGroupMembersCreateAt)
|
||||
// ChannelMembersToAdd provides a mock function with given fields: since
|
||||
func (_m *GroupStore) ChannelMembersToAdd(since int64) store.StoreChannel {
|
||||
ret := _m.Called(since)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(int64) store.StoreChannel); ok {
|
||||
r0 = rf(minGroupMembersCreateAt)
|
||||
r0 = rf(since)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
@@ -253,13 +253,45 @@ func (_m *GroupStore) PendingAutoAddChannelMembers(minGroupMembersCreateAt int64
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddTeamMembers provides a mock function with given fields: minGroupMembersCreateAt
|
||||
func (_m *GroupStore) PendingAutoAddTeamMembers(minGroupMembersCreateAt int64) store.StoreChannel {
|
||||
ret := _m.Called(minGroupMembersCreateAt)
|
||||
// TeamMembersToAdd provides a mock function with given fields: since
|
||||
func (_m *GroupStore) TeamMembersToAdd(since int64) store.StoreChannel {
|
||||
ret := _m.Called(since)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(int64) store.StoreChannel); ok {
|
||||
r0 = rf(minGroupMembersCreateAt)
|
||||
r0 = rf(since)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove provides a mock function with given fields:
|
||||
func (_m *GroupStore) ChannelMembersToRemove() store.StoreChannel {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func() store.StoreChannel); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TeamMembersToRemove provides a mock function with given fields:
|
||||
func (_m *GroupStore) TeamMembersToRemove() store.StoreChannel {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func() store.StoreChannel); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
|
||||
@@ -658,20 +658,20 @@ func (_m *LayeredStoreDatabaseLayer) OAuth() store.OAuthStore {
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddChannelMembers provides a mock function with given fields: ctx, minGroupMembersCreateAt, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) PendingAutoAddChannelMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
// ChannelMembersToAdd provides a mock function with given fields: ctx, since, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) ChannelMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, minGroupMembersCreateAt)
|
||||
_ca = append(_ca, ctx, since)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, minGroupMembersCreateAt, hints...)
|
||||
r0 = rf(ctx, since, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
@@ -681,20 +681,66 @@ func (_m *LayeredStoreDatabaseLayer) PendingAutoAddChannelMembers(ctx context.Co
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddTeamMembers provides a mock function with given fields: ctx, minGroupMembersCreateAt, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) PendingAutoAddTeamMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
// TeamMembersToAdd provides a mock function with given fields: ctx, since, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) TeamMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, minGroupMembersCreateAt)
|
||||
_ca = append(_ca, ctx, since)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, minGroupMembersCreateAt, hints...)
|
||||
r0 = rf(ctx, since, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove provides a mock function with given fields: ctx, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) ChannelMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TeamMembersToRemove provides a mock function with given fields: ctx, hints
|
||||
func (_m *LayeredStoreDatabaseLayer) TeamMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
|
||||
@@ -398,20 +398,20 @@ func (_m *LayeredStoreSupplier) Next() store.LayeredStoreSupplier {
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddChannelMembers provides a mock function with given fields: ctx, minGroupMembersCreateAt, hints
|
||||
func (_m *LayeredStoreSupplier) PendingAutoAddChannelMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
// ChannelMembersToAdd provides a mock function with given fields: ctx, since, hints
|
||||
func (_m *LayeredStoreSupplier) ChannelMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, minGroupMembersCreateAt)
|
||||
_ca = append(_ca, ctx, since)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, minGroupMembersCreateAt, hints...)
|
||||
r0 = rf(ctx, since, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
@@ -421,20 +421,66 @@ func (_m *LayeredStoreSupplier) PendingAutoAddChannelMembers(ctx context.Context
|
||||
return r0
|
||||
}
|
||||
|
||||
// PendingAutoAddTeamMembers provides a mock function with given fields: ctx, minGroupMembersCreateAt, hints
|
||||
func (_m *LayeredStoreSupplier) PendingAutoAddTeamMembers(ctx context.Context, minGroupMembersCreateAt int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
// TeamMembersToAdd provides a mock function with given fields: ctx, since, hints
|
||||
func (_m *LayeredStoreSupplier) TeamMembersToAdd(ctx context.Context, since int64, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, minGroupMembersCreateAt)
|
||||
_ca = append(_ca, ctx, since)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, minGroupMembersCreateAt, hints...)
|
||||
r0 = rf(ctx, since, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove provides a mock function with given fields: ctx, hints
|
||||
func (_m *LayeredStoreSupplier) ChannelMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// TeamMembersToRemove provides a mock function with given fields: ctx, hints
|
||||
func (_m *LayeredStoreSupplier) TeamMembersToRemove(ctx context.Context, hints ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult {
|
||||
_va := make([]interface{}, len(hints))
|
||||
for _i := range hints {
|
||||
_va[_i] = hints[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *store.LayeredStoreSupplierResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...store.LayeredStoreHint) *store.LayeredStoreSupplierResult); ok {
|
||||
r0 = rf(ctx, hints...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*store.LayeredStoreSupplierResult)
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
dn: ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: organizationalunit
|
||||
|
||||
# groupOfNames
|
||||
dn: cn=outsiders,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=board.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=board,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=board.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: uid=board.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: cn=outsiders,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=executive,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=exec.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: uid=exec.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: cn=board,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-84,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: cn=tgroup-9,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
member: uid=test.five,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-9,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: cn=tgroup-97,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-97,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=test.four,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
# groupOfUniqueNames
|
||||
dn: cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=ugroup,cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=vgroup,cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
# Adds a group with a cycle
|
||||
dn: cn=team-one-a,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.four,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=developers,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=team-one,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: uid=dev.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-one-a,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=team-two,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=developers,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev-ops.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-one,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-two,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
@@ -127,4 +127,86 @@ objectclass: iNetOrgPerson
|
||||
sn: User
|
||||
cn: Board3
|
||||
mail: success+boardthree@simulator.amazonses.com
|
||||
userPassword: Password1
|
||||
userPassword: Password1
|
||||
|
||||
dn: ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: organizationalunit
|
||||
|
||||
# groupOfNames
|
||||
dn: cn=outsiders,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=board.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=board,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=board.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: uid=board.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: cn=outsiders,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=executive,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=exec.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: uid=exec.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
member: cn=board,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-84,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: cn=tgroup-9,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
member: uid=test.five,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-9,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: cn=tgroup-97,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=tgroup-97,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfNames
|
||||
member: uid=test.four,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
# groupOfUniqueNames
|
||||
dn: cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=ugroup,cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=vgroup,cn=tgroup,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=test.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
# Adds a group with a cycle
|
||||
dn: cn=team-one-a,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.four,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=developers,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=team-one,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: uid=dev.three,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-one-a,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=team-two,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev.two,ou=testusers,dc=mm,dc=test,dc=com
|
||||
|
||||
dn: cn=developers,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
changetype: add
|
||||
objectclass: groupOfUniqueNames
|
||||
uniqueMember: uid=dev-ops.one,ou=testusers,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-one,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
uniqueMember: cn=team-two,ou=testgroups,dc=mm,dc=test,dc=com
|
||||
Ссылка в новой задаче
Block a user