MM-20644: Add users to teams as a SchemeAdmin based on a new configuration field on GroupTeams and GroupChannels records. (#13361)
* 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-20644: Use a SQL query instead of two to update Team and Channel members. * MM-20644: Fixes tests; updates query. * MM-20644: Fix permission check for patching a group syncable. * MM-20644: Fixes test for change of permissions verification in group patch API request. * MM-20644: Fix for ORM select vs insert. * MM-20644: Linting fixes. * MM-20644: Fixes some tests. * MM-20644: Skips changing the role of guests. * MM-20644: Added syncableID filtering
Этот коммит содержится в:
коммит произвёл
catalintomai
родитель
04430041a8
Коммит
605040c597
@@ -320,8 +320,9 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
appErr := verifyLinkUnlinkPermission(c, syncableType, syncableID)
|
||||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
if appErr != nil {
|
||||||
|
c.Err = appErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,8 +493,8 @@ func getGroupsByChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b, marshalErr := json.Marshal(struct {
|
b, marshalErr := json.Marshal(struct {
|
||||||
Groups []*model.Group `json:"groups"`
|
Groups []*model.GroupWithSchemeAdmin `json:"groups"`
|
||||||
Count int `json:"total_group_count"`
|
Count int `json:"total_group_count"`
|
||||||
}{
|
}{
|
||||||
Groups: groups,
|
Groups: groups,
|
||||||
Count: totalCount,
|
Count: totalCount,
|
||||||
@@ -538,8 +539,8 @@ func getGroupsByTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b, marshalErr := json.Marshal(struct {
|
b, marshalErr := json.Marshal(struct {
|
||||||
Groups []*model.Group `json:"groups"`
|
Groups []*model.GroupWithSchemeAdmin `json:"groups"`
|
||||||
Count int `json:"total_group_count"`
|
Count int `json:"total_group_count"`
|
||||||
}{
|
}{
|
||||||
Groups: groups,
|
Groups: groups,
|
||||||
Count: totalCount,
|
Count: totalCount,
|
||||||
|
|||||||
@@ -591,9 +591,18 @@ func TestPatchGroupChannel(t *testing.T) {
|
|||||||
assert.NotNil(t, groupSyncable)
|
assert.NotNil(t, groupSyncable)
|
||||||
assert.True(t, groupSyncable.AutoAdd)
|
assert.True(t, groupSyncable.AutoAdd)
|
||||||
|
|
||||||
|
role, err := th.App.GetRoleByName("channel_user")
|
||||||
|
require.Nil(t, err)
|
||||||
|
originalPermissions := role.Permissions
|
||||||
|
_, err = th.App.PatchRole(role, &model.RolePatch{Permissions: &[]string{}})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
_, response = th.Client.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch)
|
_, response = th.Client.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch)
|
||||||
assert.Equal(t, http.StatusForbidden, response.StatusCode)
|
assert.Equal(t, http.StatusForbidden, response.StatusCode)
|
||||||
|
|
||||||
|
_, err = th.App.PatchRole(role, &model.RolePatch{Permissions: &originalPermissions})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
th.App.SetLicense(nil)
|
th.App.SetLicense(nil)
|
||||||
|
|
||||||
_, response = th.SystemAdminClient.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch)
|
_, response = th.SystemAdminClient.PatchGroupSyncable(g.Id, th.BasicChannel.Id, model.GroupSyncableTypeChannel, patch)
|
||||||
@@ -645,7 +654,7 @@ func TestGetGroupsByChannel(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
_, err = th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
groupSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
AutoAdd: true,
|
AutoAdd: true,
|
||||||
SyncableId: th.BasicChannel.Id,
|
SyncableId: th.BasicChannel.Id,
|
||||||
Type: model.GroupSyncableTypeChannel,
|
Type: model.GroupSyncableTypeChannel,
|
||||||
@@ -677,7 +686,21 @@ func TestGetGroupsByChannel(t *testing.T) {
|
|||||||
|
|
||||||
groups, _, response := th.SystemAdminClient.GetGroupsByChannel(th.BasicChannel.Id, opts)
|
groups, _, response := th.SystemAdminClient.GetGroupsByChannel(th.BasicChannel.Id, opts)
|
||||||
assert.Nil(t, response.Error)
|
assert.Nil(t, response.Error)
|
||||||
assert.ElementsMatch(t, []*model.Group{group}, groups)
|
assert.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(false)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
require.False(t, *groups[0].SchemeAdmin)
|
||||||
|
|
||||||
|
// set syncable to true
|
||||||
|
groupSyncable.SchemeAdmin = true
|
||||||
|
_, err = th.App.UpdateGroupSyncable(groupSyncable)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// ensure that SchemeAdmin field is updated
|
||||||
|
groups, _, response = th.SystemAdminClient.GetGroupsByChannel(th.BasicChannel.Id, opts)
|
||||||
|
assert.Nil(t, response.Error)
|
||||||
|
assert.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(true)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
require.True(t, *groups[0].SchemeAdmin)
|
||||||
|
|
||||||
groups, _, response = th.SystemAdminClient.GetGroupsByChannel(model.NewId(), opts)
|
groups, _, response = th.SystemAdminClient.GetGroupsByChannel(model.NewId(), opts)
|
||||||
assert.Equal(t, "store.sql_channel.get.existing.app_error", response.Error.Id)
|
assert.Equal(t, "store.sql_channel.get.existing.app_error", response.Error.Id)
|
||||||
@@ -698,7 +721,7 @@ func TestGetGroupsByTeam(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
_, err = th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
groupSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
AutoAdd: true,
|
AutoAdd: true,
|
||||||
SyncableId: th.BasicTeam.Id,
|
SyncableId: th.BasicTeam.Id,
|
||||||
Type: model.GroupSyncableTypeTeam,
|
Type: model.GroupSyncableTypeTeam,
|
||||||
@@ -728,7 +751,21 @@ func TestGetGroupsByTeam(t *testing.T) {
|
|||||||
|
|
||||||
groups, _, response := th.SystemAdminClient.GetGroupsByTeam(th.BasicTeam.Id, opts)
|
groups, _, response := th.SystemAdminClient.GetGroupsByTeam(th.BasicTeam.Id, opts)
|
||||||
assert.Nil(t, response.Error)
|
assert.Nil(t, response.Error)
|
||||||
assert.ElementsMatch(t, []*model.Group{group}, groups)
|
assert.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(false)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
require.False(t, *groups[0].SchemeAdmin)
|
||||||
|
|
||||||
|
// set syncable to true
|
||||||
|
groupSyncable.SchemeAdmin = true
|
||||||
|
_, err = th.App.UpdateGroupSyncable(groupSyncable)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// ensure that SchemeAdmin field is updated
|
||||||
|
groups, _, response = th.SystemAdminClient.GetGroupsByTeam(th.BasicTeam.Id, opts)
|
||||||
|
assert.Nil(t, response.Error)
|
||||||
|
assert.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(true)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
require.True(t, *groups[0].SchemeAdmin)
|
||||||
|
|
||||||
groups, _, response = th.SystemAdminClient.GetGroupsByTeam(model.NewId(), opts)
|
groups, _, response = th.SystemAdminClient.GetGroupsByTeam(model.NewId(), opts)
|
||||||
assert.Nil(t, response.Error)
|
assert.Nil(t, response.Error)
|
||||||
|
|||||||
@@ -971,6 +971,16 @@ func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMem
|
|||||||
SchemeGuest: user.IsGuest(),
|
SchemeGuest: user.IsGuest(),
|
||||||
SchemeUser: !user.IsGuest(),
|
SchemeUser: !user.IsGuest(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !user.IsGuest() {
|
||||||
|
var userShouldBeAdmin bool
|
||||||
|
userShouldBeAdmin, err = a.UserIsInAdminRoleGroup(user.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newMember.SchemeAdmin = userShouldBeAdmin
|
||||||
|
}
|
||||||
|
|
||||||
if _, err = a.Srv.Store.Channel().SaveMember(newMember); err != nil {
|
if _, err = a.Srv.Store.Channel().SaveMember(newMember); err != nil {
|
||||||
mlog.Error("Failed to add member", mlog.String("user_id", user.Id), mlog.String("channel_id", channel.Id), mlog.Err(err))
|
mlog.Error("Failed to add member", mlog.String("user_id", user.Id), mlog.String("channel_id", channel.Id), mlog.Err(err))
|
||||||
return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "", http.StatusInternalServerError)
|
return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -1161,3 +1161,55 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
|||||||
assert.Nil(t, response)
|
assert.Nil(t, response)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddUserToChannel(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
user1 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
|
||||||
|
ruser1, _ := th.App.CreateUser(&user1)
|
||||||
|
defer th.App.PermanentDeleteUser(&user1)
|
||||||
|
th.App.AddTeamMember(th.BasicTeam.Id, ruser1.Id)
|
||||||
|
|
||||||
|
group := th.CreateGroup()
|
||||||
|
|
||||||
|
_, err := th.App.UpsertGroupMember(group.Id, user1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
gs, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: th.BasicChannel.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
GroupId: group.Id,
|
||||||
|
SchemeAdmin: false,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
err = th.App.JoinChannel(th.BasicChannel, ruser1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// verify user was added as a non-admin
|
||||||
|
cm1, err := th.App.GetChannelMember(th.BasicChannel.Id, ruser1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.False(t, cm1.SchemeAdmin)
|
||||||
|
|
||||||
|
user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
|
||||||
|
ruser2, _ := th.App.CreateUser(&user2)
|
||||||
|
defer th.App.PermanentDeleteUser(&user2)
|
||||||
|
th.App.AddTeamMember(th.BasicTeam.Id, ruser2.Id)
|
||||||
|
|
||||||
|
_, err = th.App.UpsertGroupMember(group.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
gs.SchemeAdmin = true
|
||||||
|
_, err = th.App.UpdateGroupSyncable(gs)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
err = th.App.JoinChannel(th.BasicChannel, ruser2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// verify user was added as an admin
|
||||||
|
cm2, err := th.App.GetChannelMember(th.BasicChannel.Id, ruser2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, cm2.SchemeAdmin)
|
||||||
|
}
|
||||||
|
|||||||
19
app/group.go
19
app/group.go
@@ -168,7 +168,7 @@ func (a *App) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError)
|
|||||||
return a.Srv.Store.Group().ChannelMembersToRemove()
|
return a.Srv.Store.Group().ChannelMembersToRemove()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.Group, int, *model.AppError) {
|
func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, int, *model.AppError) {
|
||||||
groups, err := a.Srv.Store.Group().GetGroupsByChannel(channelId, opts)
|
groups, err := a.Srv.Store.Group().GetGroupsByChannel(channelId, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -182,7 +182,7 @@ func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) (
|
|||||||
return groups, int(count), nil
|
return groups, int(count), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.Group, int, *model.AppError) {
|
func (a *App) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, int, *model.AppError) {
|
||||||
groups, err := a.Srv.Store.Group().GetGroupsByTeam(teamId, opts)
|
groups, err := a.Srv.Store.Group().GetGroupsByTeam(teamId, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -313,3 +313,18 @@ func (a *App) ChannelMembersMinusGroupMembers(channelID string, groupIDs []strin
|
|||||||
}
|
}
|
||||||
return users, totalCount, nil
|
return users, totalCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserIsInAdminRoleGroup returns true at least one of the user's groups are configured to set the members as
|
||||||
|
// admins in the given syncable.
|
||||||
|
func (a *App) UserIsInAdminRoleGroup(userID, syncableID string, syncableType model.GroupSyncableType) (bool, *model.AppError) {
|
||||||
|
groupIDs, err := a.Srv.Store.Group().AdminRoleGroupsForSyncableMember(userID, syncableID, syncableType)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(groupIDs) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -235,7 +235,8 @@ func TestGetGroupsByChannel(t *testing.T) {
|
|||||||
|
|
||||||
groups, _, err := th.App.GetGroupsByChannel(th.BasicChannel.Id, opts)
|
groups, _, err := th.App.GetGroupsByChannel(th.BasicChannel.Id, opts)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.ElementsMatch(t, []*model.Group{group}, groups)
|
require.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(false)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
|
||||||
groups, _, err = th.App.GetGroupsByChannel(model.NewId(), opts)
|
groups, _, err = th.App.GetGroupsByChannel(model.NewId(), opts)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
@@ -261,7 +262,8 @@ func TestGetGroupsByTeam(t *testing.T) {
|
|||||||
|
|
||||||
groups, _, err := th.App.GetGroupsByTeam(th.BasicTeam.Id, model.GroupSearchOpts{})
|
groups, _, err := th.App.GetGroupsByTeam(th.BasicTeam.Id, model.GroupSearchOpts{})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.ElementsMatch(t, []*model.Group{group}, groups)
|
require.ElementsMatch(t, []*model.GroupWithSchemeAdmin{{Group: *group, SchemeAdmin: model.NewBool(false)}}, groups)
|
||||||
|
require.NotNil(t, groups[0].SchemeAdmin)
|
||||||
|
|
||||||
groups, _, err = th.App.GetGroupsByTeam(model.NewId(), model.GroupSearchOpts{})
|
groups, _, err = th.App.GetGroupsByTeam(model.NewId(), model.GroupSearchOpts{})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
@@ -277,3 +279,55 @@ func TestGetGroups(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.ElementsMatch(t, []*model.Group{group}, groups)
|
require.ElementsMatch(t, []*model.Group{group}, groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserIsInAdminRoleGroup(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
group1 := th.CreateGroup()
|
||||||
|
group2 := th.CreateGroup()
|
||||||
|
|
||||||
|
g, err := th.App.UpsertGroupMember(group1.Id, th.BasicUser.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.NotNil(t, g)
|
||||||
|
|
||||||
|
g, err = th.App.UpsertGroupMember(group2.Id, th.BasicUser.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.NotNil(t, g)
|
||||||
|
|
||||||
|
_, err = th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
|
GroupId: group1.Id,
|
||||||
|
AutoAdd: false,
|
||||||
|
SyncableId: th.BasicTeam.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
groupSyncable2, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
|
GroupId: group2.Id,
|
||||||
|
AutoAdd: false,
|
||||||
|
SyncableId: th.BasicTeam.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// no syncables are set to scheme admin true, so this returns false
|
||||||
|
actual, err := th.App.UserIsInAdminRoleGroup(th.BasicUser.Id, th.BasicTeam.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.False(t, actual)
|
||||||
|
|
||||||
|
// set a syncable to be scheme admins
|
||||||
|
groupSyncable2.SchemeAdmin = true
|
||||||
|
_, err = th.App.UpdateGroupSyncable(groupSyncable2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// a syncable is set to scheme admin true, so this returns true
|
||||||
|
actual, err = th.App.UserIsInAdminRoleGroup(th.BasicUser.Id, th.BasicTeam.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, actual)
|
||||||
|
|
||||||
|
// delete the syncable, should be false again
|
||||||
|
th.App.DeleteGroupSyncable(group2.Id, th.BasicTeam.Id, model.GroupSyncableTypeTeam)
|
||||||
|
actual, err = th.App.UserIsInAdminRoleGroup(th.BasicUser.Id, th.BasicTeam.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.False(t, actual)
|
||||||
|
}
|
||||||
|
|||||||
@@ -543,6 +543,14 @@ func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMem
|
|||||||
SchemeUser: !user.IsGuest(),
|
SchemeUser: !user.IsGuest(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !user.IsGuest() {
|
||||||
|
userShouldBeAdmin, err := a.UserIsInAdminRoleGroup(user.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
tm.SchemeAdmin = userShouldBeAdmin
|
||||||
|
}
|
||||||
|
|
||||||
if team.Email == user.Email {
|
if team.Email == user.Email {
|
||||||
tm.SchemeAdmin = true
|
tm.SchemeAdmin = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -639,7 +639,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
|||||||
ruser, _ := th.App.CreateUser(&user)
|
ruser, _ := th.App.CreateUser(&user)
|
||||||
defer th.App.PermanentDeleteUser(&user)
|
defer th.App.PermanentDeleteUser(&user)
|
||||||
|
|
||||||
_, alreadyAdded, err := th.App.joinUserToTeam(team, ruser)
|
var alreadyAdded bool
|
||||||
|
_, alreadyAdded, err = th.App.joinUserToTeam(team, ruser)
|
||||||
require.False(t, alreadyAdded, "Should return already added equal to false")
|
require.False(t, alreadyAdded, "Should return already added equal to false")
|
||||||
require.Nil(t, err, "Should return no error")
|
require.Nil(t, err, "Should return no error")
|
||||||
})
|
})
|
||||||
@@ -651,7 +652,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
|||||||
|
|
||||||
th.App.joinUserToTeam(team, ruser)
|
th.App.joinUserToTeam(team, ruser)
|
||||||
|
|
||||||
_, alreadyAdded, err := th.App.joinUserToTeam(team, ruser)
|
var alreadyAdded bool
|
||||||
|
_, alreadyAdded, err = th.App.joinUserToTeam(team, ruser)
|
||||||
require.True(t, alreadyAdded, "Should return already added")
|
require.True(t, alreadyAdded, "Should return already added")
|
||||||
require.Nil(t, err, "Should return no error")
|
require.Nil(t, err, "Should return no error")
|
||||||
})
|
})
|
||||||
@@ -664,7 +666,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
|||||||
th.App.joinUserToTeam(team, ruser)
|
th.App.joinUserToTeam(team, ruser)
|
||||||
th.App.LeaveTeam(team, ruser, ruser.Id)
|
th.App.LeaveTeam(team, ruser, ruser.Id)
|
||||||
|
|
||||||
_, alreadyAdded, err := th.App.joinUserToTeam(team, ruser)
|
var alreadyAdded bool
|
||||||
|
_, alreadyAdded, err = th.App.joinUserToTeam(team, ruser)
|
||||||
require.False(t, alreadyAdded, "Should return already added equal to false")
|
require.False(t, alreadyAdded, "Should return already added equal to false")
|
||||||
require.Nil(t, err, "Should return no error")
|
require.Nil(t, err, "Should return no error")
|
||||||
})
|
})
|
||||||
@@ -679,7 +682,7 @@ func TestJoinUserToTeam(t *testing.T) {
|
|||||||
defer th.App.PermanentDeleteUser(&user2)
|
defer th.App.PermanentDeleteUser(&user2)
|
||||||
th.App.joinUserToTeam(team, ruser1)
|
th.App.joinUserToTeam(team, ruser1)
|
||||||
|
|
||||||
_, _, err := th.App.joinUserToTeam(team, ruser2)
|
_, _, err = th.App.joinUserToTeam(team, ruser2)
|
||||||
require.NotNil(t, err, "Should fail")
|
require.NotNil(t, err, "Should fail")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -697,9 +700,50 @@ func TestJoinUserToTeam(t *testing.T) {
|
|||||||
th.App.LeaveTeam(team, ruser1, ruser1.Id)
|
th.App.LeaveTeam(team, ruser1, ruser1.Id)
|
||||||
th.App.joinUserToTeam(team, ruser2)
|
th.App.joinUserToTeam(team, ruser2)
|
||||||
|
|
||||||
_, _, err := th.App.joinUserToTeam(team, ruser1)
|
_, _, err = th.App.joinUserToTeam(team, ruser1)
|
||||||
require.NotNil(t, err, "Should fail")
|
require.NotNil(t, err, "Should fail")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("new join with correct scheme_admin value from group syncable", func(t *testing.T) {
|
||||||
|
user1 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
|
||||||
|
ruser1, _ := th.App.CreateUser(&user1)
|
||||||
|
defer th.App.PermanentDeleteUser(&user1)
|
||||||
|
|
||||||
|
group := th.CreateGroup()
|
||||||
|
|
||||||
|
_, err = th.App.UpsertGroupMember(group.Id, user1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
gs, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: team.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
GroupId: group.Id,
|
||||||
|
SchemeAdmin: false,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.MaxUsersPerTeam = model.NewInt(999) })
|
||||||
|
|
||||||
|
tm1, _, err := th.App.joinUserToTeam(team, ruser1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.False(t, tm1.SchemeAdmin)
|
||||||
|
|
||||||
|
user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
|
||||||
|
ruser2, _ := th.App.CreateUser(&user2)
|
||||||
|
defer th.App.PermanentDeleteUser(&user2)
|
||||||
|
|
||||||
|
_, err = th.App.UpsertGroupMember(group.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
gs.SchemeAdmin = true
|
||||||
|
_, err = th.App.UpdateGroupSyncable(gs)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
tm2, _, err := th.App.joinUserToTeam(team, ruser2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, tm2.SchemeAdmin)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppUpdateTeamScheme(t *testing.T) {
|
func TestAppUpdateTeamScheme(t *testing.T) {
|
||||||
|
|||||||
@@ -3612,7 +3612,7 @@ func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetGroupsByChannel retrieves the Mattermost Groups associated with a given channel
|
// GetGroupsByChannel retrieves the Mattermost Groups associated with a given channel
|
||||||
func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]*Group, int, *Response) {
|
func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) {
|
||||||
path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v", c.GetChannelRoute(channelId), opts.Q, opts.IncludeMemberCount)
|
path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v", c.GetChannelRoute(channelId), opts.Q, opts.IncludeMemberCount)
|
||||||
if opts.PageOpts != nil {
|
if opts.PageOpts != nil {
|
||||||
path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
|
path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
|
||||||
@@ -3624,8 +3624,8 @@ func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]
|
|||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
|
|
||||||
responseData := struct {
|
responseData := struct {
|
||||||
Groups []*Group `json:"groups"`
|
Groups []*GroupWithSchemeAdmin `json:"groups"`
|
||||||
Count int `json:"total_group_count"`
|
Count int `json:"total_group_count"`
|
||||||
}{}
|
}{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
|
||||||
appErr := NewAppError("Api4.GetGroupsByChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
appErr := NewAppError("Api4.GetGroupsByChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -3636,7 +3636,7 @@ func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetGroupsByTeam retrieves the Mattermost Groups associated with a given team
|
// GetGroupsByTeam retrieves the Mattermost Groups associated with a given team
|
||||||
func (c *Client4) GetGroupsByTeam(teamId string, opts GroupSearchOpts) ([]*Group, int, *Response) {
|
func (c *Client4) GetGroupsByTeam(teamId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) {
|
||||||
path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v", c.GetTeamRoute(teamId), opts.Q, opts.IncludeMemberCount)
|
path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v", c.GetTeamRoute(teamId), opts.Q, opts.IncludeMemberCount)
|
||||||
if opts.PageOpts != nil {
|
if opts.PageOpts != nil {
|
||||||
path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
|
path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
|
||||||
@@ -3648,8 +3648,8 @@ func (c *Client4) GetGroupsByTeam(teamId string, opts GroupSearchOpts) ([]*Group
|
|||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
|
|
||||||
responseData := struct {
|
responseData := struct {
|
||||||
Groups []*Group `json:"groups"`
|
Groups []*GroupWithSchemeAdmin `json:"groups"`
|
||||||
Count int `json:"total_group_count"`
|
Count int `json:"total_group_count"`
|
||||||
}{}
|
}{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
|
||||||
appErr := NewAppError("Api4.GetGroupsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
appErr := NewAppError("Api4.GetGroupsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ type Group struct {
|
|||||||
MemberCount *int `db:"-" json:"member_count,omitempty"`
|
MemberCount *int `db:"-" json:"member_count,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GroupWithSchemeAdmin struct {
|
||||||
|
Group
|
||||||
|
SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type GroupPatch struct {
|
type GroupPatch struct {
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
DisplayName *string `json:"display_name"`
|
DisplayName *string `json:"display_name"`
|
||||||
|
|||||||
@@ -29,11 +29,12 @@ type GroupSyncable struct {
|
|||||||
// TeamId.
|
// TeamId.
|
||||||
SyncableId string `db:"-" json:"-"`
|
SyncableId string `db:"-" json:"-"`
|
||||||
|
|
||||||
AutoAdd bool `json:"auto_add"`
|
AutoAdd bool `json:"auto_add"`
|
||||||
CreateAt int64 `json:"create_at"`
|
SchemeAdmin bool `json:"scheme_admin"`
|
||||||
DeleteAt int64 `json:"delete_at"`
|
CreateAt int64 `json:"create_at"`
|
||||||
UpdateAt int64 `json:"update_at"`
|
DeleteAt int64 `json:"delete_at"`
|
||||||
Type GroupSyncableType `db:"-" json:"-"`
|
UpdateAt int64 `json:"update_at"`
|
||||||
|
Type GroupSyncableType `db:"-" json:"-"`
|
||||||
|
|
||||||
// Values joined in from the associated team and/or channel
|
// Values joined in from the associated team and/or channel
|
||||||
ChannelDisplayName string `db:"-" json:"-"`
|
ChannelDisplayName string `db:"-" json:"-"`
|
||||||
@@ -123,13 +124,17 @@ func (syncable *GroupSyncable) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GroupSyncablePatch struct {
|
type GroupSyncablePatch struct {
|
||||||
AutoAdd *bool `json:"auto_add"`
|
AutoAdd *bool `json:"auto_add"`
|
||||||
|
SchemeAdmin *bool `json:"scheme_admin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (syncable *GroupSyncable) Patch(patch *GroupSyncablePatch) {
|
func (syncable *GroupSyncable) Patch(patch *GroupSyncablePatch) {
|
||||||
if patch.AutoAdd != nil {
|
if patch.AutoAdd != nil {
|
||||||
syncable.AutoAdd = *patch.AutoAdd
|
syncable.AutoAdd = *patch.AutoAdd
|
||||||
}
|
}
|
||||||
|
if patch.SchemeAdmin != nil {
|
||||||
|
syncable.SchemeAdmin = *patch.SchemeAdmin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserTeamIDPair struct {
|
type UserTeamIDPair struct {
|
||||||
|
|||||||
@@ -2838,3 +2838,25 @@ func (s SqlChannelStore) UserBelongsToChannels(userId string, channelIds []strin
|
|||||||
}
|
}
|
||||||
return c > 0, nil
|
return c > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlChannelStore) UpdateMembersRole(channelID string, userIDs []string) *model.AppError {
|
||||||
|
sql := fmt.Sprintf(`
|
||||||
|
UPDATE
|
||||||
|
ChannelMembers
|
||||||
|
SET
|
||||||
|
SchemeAdmin = CASE WHEN UserId IN ('%s') THEN
|
||||||
|
TRUE
|
||||||
|
ELSE
|
||||||
|
FALSE
|
||||||
|
END
|
||||||
|
WHERE
|
||||||
|
ChannelId = :ChannelId
|
||||||
|
AND (SchemeGuest = false OR SchemeGuest IS NULL)
|
||||||
|
`, strings.Join(userIDs, "', '"))
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec(sql, map[string]interface{}{"ChannelId": channelID}); err != nil {
|
||||||
|
return model.NewAppError("SqlChannelStore.UpdateMembersRole", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ func (s *SqlGroupStore) CreateIndexesIfNotExists() {
|
|||||||
s.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
|
s.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
|
||||||
s.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(1)", "boolean")
|
s.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(1)", "boolean")
|
||||||
s.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(1)", "boolean")
|
s.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(1)", "boolean")
|
||||||
|
s.CreateIndexIfNotExists("idx_groupteams_schemeadmin", "GroupTeams", "SchemeAdmin")
|
||||||
|
s.CreateIndexIfNotExists("idx_groupchannels_schemeadmin", "GroupChannels", "SchemeAdmin")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, *model.AppError) {
|
func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, *model.AppError) {
|
||||||
@@ -512,6 +514,7 @@ func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableTy
|
|||||||
Type: syncableType,
|
Type: syncableType,
|
||||||
TeamDisplayName: result.TeamDisplayName,
|
TeamDisplayName: result.TeamDisplayName,
|
||||||
TeamType: result.TeamType,
|
TeamType: result.TeamType,
|
||||||
|
SchemeAdmin: result.SchemeAdmin,
|
||||||
}
|
}
|
||||||
groupSyncables = append(groupSyncables, groupSyncable)
|
groupSyncables = append(groupSyncables, groupSyncable)
|
||||||
}
|
}
|
||||||
@@ -550,6 +553,7 @@ func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableTy
|
|||||||
TeamDisplayName: result.TeamDisplayName,
|
TeamDisplayName: result.TeamDisplayName,
|
||||||
TeamType: result.TeamType,
|
TeamType: result.TeamType,
|
||||||
TeamID: result.TeamID,
|
TeamID: result.TeamID,
|
||||||
|
SchemeAdmin: result.SchemeAdmin,
|
||||||
}
|
}
|
||||||
groupSyncables = append(groupSyncables, groupSyncable)
|
groupSyncables = append(groupSyncables, groupSyncable)
|
||||||
}
|
}
|
||||||
@@ -784,7 +788,7 @@ func (s *SqlGroupStore) CountGroupsByChannel(channelId string, opts model.GroupS
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectGroups, channelId, opts)
|
query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectGroups, channelId, opts)
|
||||||
|
|
||||||
if opts.PageOpts != nil {
|
if opts.PageOpts != nil {
|
||||||
@@ -797,7 +801,7 @@ func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSea
|
|||||||
return nil, model.NewAppError("SqlGroupStore.GetGroupsByChannel", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("SqlGroupStore.GetGroupsByChannel", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var groups []*model.Group
|
var groups []*model.GroupWithSchemeAdmin
|
||||||
|
|
||||||
_, err = s.GetReplica().Select(&groups, queryString, args...)
|
_, err = s.GetReplica().Select(&groups, queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -861,7 +865,7 @@ func (s *SqlGroupStore) ChannelMembersToRemove() ([]*model.ChannelMember, *model
|
|||||||
|
|
||||||
func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t selectType, syncableID string, opts model.GroupSearchOpts) sq.SelectBuilder {
|
func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t selectType, syncableID string, opts model.GroupSearchOpts) sq.SelectBuilder {
|
||||||
selectStrs := map[selectType]string{
|
selectStrs := map[selectType]string{
|
||||||
selectGroups: "ug.*",
|
selectGroups: "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin",
|
||||||
selectCountGroups: "COUNT(*)",
|
selectCountGroups: "COUNT(*)",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,7 +887,7 @@ func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t
|
|||||||
|
|
||||||
if opts.IncludeMemberCount && t == selectGroups {
|
if opts.IncludeMemberCount && t == selectGroups {
|
||||||
query = s.getQueryBuilder().
|
query = s.getQueryBuilder().
|
||||||
Select("ug.*, coalesce(Members.MemberCount, 0) AS MemberCount").
|
Select(fmt.Sprintf("ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, Group%ss.SchemeAdmin AS SyncableSchemeAdmin", st)).
|
||||||
From("UserGroups ug").
|
From("UserGroups ug").
|
||||||
LeftJoin("(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = ug.Id").
|
LeftJoin("(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = ug.Id").
|
||||||
LeftJoin(fmt.Sprintf("%[1]s ON %[1]s.GroupId = ug.Id", table)).
|
LeftJoin(fmt.Sprintf("%[1]s ON %[1]s.GroupId = ug.Id", table)).
|
||||||
@@ -919,7 +923,7 @@ func (s *SqlGroupStore) CountGroupsByTeam(teamId string, opts model.GroupSearchO
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectGroups, teamId, opts)
|
query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectGroups, teamId, opts)
|
||||||
|
|
||||||
if opts.PageOpts != nil {
|
if opts.PageOpts != nil {
|
||||||
@@ -932,7 +936,7 @@ func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpt
|
|||||||
return nil, model.NewAppError("SqlGroupStore.GetGroupsByTeam", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("SqlGroupStore.GetGroupsByTeam", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var groups []*model.Group
|
var groups []*model.GroupWithSchemeAdmin
|
||||||
|
|
||||||
_, err = s.GetReplica().Select(&groups, queryString, args...)
|
_, err = s.GetReplica().Select(&groups, queryString, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1164,3 +1168,46 @@ func (s *SqlGroupStore) CountChannelMembersMinusGroupMembers(channelID string, g
|
|||||||
|
|
||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SqlGroupStore) AdminRoleGroupsForSyncableMember(userID, syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
var groupIds []string
|
||||||
|
|
||||||
|
sql := fmt.Sprintf(`
|
||||||
|
SELECT
|
||||||
|
GroupMembers.GroupId
|
||||||
|
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
|
||||||
|
AND Group%[1]ss.SchemeAdmin = TRUE`, syncableType)
|
||||||
|
|
||||||
|
_, err := s.GetReplica().Select(&groupIds, sql, map[string]interface{}{"UserId": userID, fmt.Sprintf("%sId", syncableType): syncableID})
|
||||||
|
if err != nil {
|
||||||
|
return nil, model.NewAppError("SqlGroupStore AdminRoleGroupsForSyncableMember", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupIds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SqlGroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
query := s.getQueryBuilder().Select("UserId").
|
||||||
|
From(fmt.Sprintf("Group%ss", syncableType)).
|
||||||
|
Join(fmt.Sprintf("GroupMembers ON GroupMembers.GroupId = Group%ss.GroupId AND Group%[1]ss.SchemeAdmin = TRUE AND GroupMembers.DeleteAt = 0", syncableType.String())).Where(fmt.Sprintf("Group%[1]ss.%[1]sId = ?", syncableType.String()), syncableID)
|
||||||
|
|
||||||
|
sql, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, model.NewAppError("SqlGroupStore.PermittedSyncableAdmins", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
var userIDs []string
|
||||||
|
if _, err = s.GetReplica().Select(&userIDs, sql, args...); err != nil {
|
||||||
|
return nil, model.NewAppError("SqlGroupStore.PermittedSyncableAdmins", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userIDs, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1080,6 +1080,28 @@ func (s SqlTeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool,
|
|||||||
return c > 0, nil
|
return c > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SqlTeamStore) UpdateMembersRole(teamID string, userIDs []string) *model.AppError {
|
||||||
|
sql := fmt.Sprintf(`
|
||||||
|
UPDATE
|
||||||
|
TeamMembers
|
||||||
|
SET
|
||||||
|
SchemeAdmin = CASE WHEN UserId IN ('%s') THEN
|
||||||
|
TRUE
|
||||||
|
ELSE
|
||||||
|
FALSE
|
||||||
|
END
|
||||||
|
WHERE
|
||||||
|
TeamId = :TeamId
|
||||||
|
AND (SchemeGuest = false OR SchemeGuest IS NULL)
|
||||||
|
AND DeleteAt = 0`, strings.Join(userIDs, "', '"))
|
||||||
|
|
||||||
|
if _, err := s.GetMaster().Exec(sql, map[string]interface{}{"TeamId": teamID}); err != nil {
|
||||||
|
return model.NewAppError("SqlTeamStore.UpdateMembersRole", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func applyTeamMemberViewRestrictionsFilter(query sq.SelectBuilder, teamId string, restrictions *model.ViewUsersRestrictions) sq.SelectBuilder {
|
func applyTeamMemberViewRestrictionsFilter(query sq.SelectBuilder, teamId string, restrictions *model.ViewUsersRestrictions) sq.SelectBuilder {
|
||||||
if restrictions == nil {
|
if restrictions == nil {
|
||||||
return query
|
return query
|
||||||
|
|||||||
@@ -754,6 +754,12 @@ func upgradeDatabaseToVersion520(sqlStore SqlStore) {
|
|||||||
|
|
||||||
sqlStore.CreateColumnIfNotExistsNoDefault("Bots", "LastIconUpdate", "bigint", "bigint")
|
sqlStore.CreateColumnIfNotExistsNoDefault("Bots", "LastIconUpdate", "bigint", "bigint")
|
||||||
|
|
||||||
|
sqlStore.CreateColumnIfNotExists("GroupTeams", "SchemeAdmin", "boolean", "boolean", "0")
|
||||||
|
sqlStore.CreateIndexIfNotExists("idx_groupteams_schemeadmin", "GroupTeams", "SchemeAdmin")
|
||||||
|
|
||||||
|
sqlStore.CreateColumnIfNotExists("GroupChannels", "SchemeAdmin", "boolean", "boolean", "0")
|
||||||
|
sqlStore.CreateIndexIfNotExists("idx_groupchannels_schemeadmin", "GroupChannels", "SchemeAdmin")
|
||||||
|
|
||||||
// saveSchemaVersion(sqlStore, VERSION_5_20_0)
|
// saveSchemaVersion(sqlStore, VERSION_5_20_0)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ type TeamStore interface {
|
|||||||
GetUserTeamIds(userId string, allowFromCache bool) ([]string, *model.AppError)
|
GetUserTeamIds(userId string, allowFromCache bool) ([]string, *model.AppError)
|
||||||
InvalidateAllTeamIdsForUser(userId string)
|
InvalidateAllTeamIdsForUser(userId string)
|
||||||
ClearCaches()
|
ClearCaches()
|
||||||
|
|
||||||
|
// UpdateMembersRole sets all of the given team members to admins and all of the other members of the team to
|
||||||
|
// non-admin members.
|
||||||
|
UpdateMembersRole(teamID string, userIDs []string) *model.AppError
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelStore interface {
|
type ChannelStore interface {
|
||||||
@@ -190,6 +194,10 @@ type ChannelStore interface {
|
|||||||
RemoveAllDeactivatedMembers(channelId string) *model.AppError
|
RemoveAllDeactivatedMembers(channelId string) *model.AppError
|
||||||
GetChannelsBatchForIndexing(startTime, endTime int64, limit int) ([]*model.Channel, *model.AppError)
|
GetChannelsBatchForIndexing(startTime, endTime int64, limit int) ([]*model.Channel, *model.AppError)
|
||||||
UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError)
|
UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError)
|
||||||
|
|
||||||
|
// UpdateMembersRole sets all of the given team members to admins and all of the other members of the team to
|
||||||
|
// non-admin members.
|
||||||
|
UpdateMembersRole(channelID string, userIDs []string) *model.AppError
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelMemberHistoryStore interface {
|
type ChannelMemberHistoryStore interface {
|
||||||
@@ -599,10 +607,10 @@ type GroupStore interface {
|
|||||||
TeamMembersToRemove() ([]*model.TeamMember, *model.AppError)
|
TeamMembersToRemove() ([]*model.TeamMember, *model.AppError)
|
||||||
ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError)
|
ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError)
|
||||||
|
|
||||||
GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError)
|
GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError)
|
||||||
CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, *model.AppError)
|
CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, *model.AppError)
|
||||||
|
|
||||||
GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError)
|
GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError)
|
||||||
CountGroupsByTeam(teamId string, opts model.GroupSearchOpts) (int64, *model.AppError)
|
CountGroupsByTeam(teamId string, opts model.GroupSearchOpts) (int64, *model.AppError)
|
||||||
|
|
||||||
GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError)
|
GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError)
|
||||||
@@ -611,6 +619,14 @@ type GroupStore interface {
|
|||||||
CountTeamMembersMinusGroupMembers(teamID string, groupIDs []string) (int64, *model.AppError)
|
CountTeamMembersMinusGroupMembers(teamID string, groupIDs []string) (int64, *model.AppError)
|
||||||
ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, *model.AppError)
|
ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, *model.AppError)
|
||||||
CountChannelMembersMinusGroupMembers(channelID string, groupIDs []string) (int64, *model.AppError)
|
CountChannelMembersMinusGroupMembers(channelID string, groupIDs []string) (int64, *model.AppError)
|
||||||
|
|
||||||
|
// AdminRoleGroupsForSyncableMember returns the IDs of all of the groups that the user is a member of that are
|
||||||
|
// configured as SchemeAdmin: true for the given syncable.
|
||||||
|
AdminRoleGroupsForSyncableMember(userID, syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError)
|
||||||
|
|
||||||
|
// PermittedSyncableAdmins returns the IDs of all of the user who are permitted by the group syncable to have
|
||||||
|
// the admin role for the given syncable.
|
||||||
|
PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError)
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkMetadataStore interface {
|
type LinkMetadataStore interface {
|
||||||
|
|||||||
@@ -56,6 +56,13 @@ func TestGroupStore(t *testing.T, ss store.Store) {
|
|||||||
t.Run("ChannelMembersMinusGroupMembers", func(t *testing.T) { testChannelMembersMinusGroupMembers(t, ss) })
|
t.Run("ChannelMembersMinusGroupMembers", func(t *testing.T) { testChannelMembersMinusGroupMembers(t, ss) })
|
||||||
|
|
||||||
t.Run("GetMemberCount", func(t *testing.T) { groupTestGetMemberCount(t, ss) })
|
t.Run("GetMemberCount", func(t *testing.T) { groupTestGetMemberCount(t, ss) })
|
||||||
|
|
||||||
|
t.Run("AdminRoleGroupsForSyncableMember_Channel", func(t *testing.T) { groupTestAdminRoleGroupsForSyncableMemberChannel(t, ss) })
|
||||||
|
t.Run("AdminRoleGroupsForSyncableMember_Team", func(t *testing.T) { groupTestAdminRoleGroupsForSyncableMemberTeam(t, ss) })
|
||||||
|
t.Run("PermittedSyncableAdmins_Team", func(t *testing.T) { groupTestPermittedSyncableAdminsTeam(t, ss) })
|
||||||
|
t.Run("PermittedSyncableAdmins_Channel", func(t *testing.T) { groupTestPermittedSyncableAdminsChannel(t, ss) })
|
||||||
|
t.Run("UpdateMembersRole_Team", func(t *testing.T) { groupTestpUpdateMembersRoleTeam(t, ss) })
|
||||||
|
t.Run("UpdateMembersRole_Channel", func(t *testing.T) { groupTestpUpdateMembersRoleChannel(t, ss) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGroupStoreCreate(t *testing.T, ss store.Store) {
|
func testGroupStoreCreate(t *testing.T, ss store.Store) {
|
||||||
@@ -916,7 +923,9 @@ func testGetAllGroupSyncablesByGroup(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
// create groupteam
|
// create groupteam
|
||||||
var groupTeam *model.GroupSyncable
|
var groupTeam *model.GroupSyncable
|
||||||
groupTeam, err = ss.Group().CreateGroupSyncable(model.NewGroupTeam(group.Id, team.Id, false))
|
gt := model.NewGroupTeam(group.Id, team.Id, false)
|
||||||
|
gt.SchemeAdmin = true
|
||||||
|
groupTeam, err = ss.Group().CreateGroupSyncable(gt)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
groupTeams = append(groupTeams, groupTeam)
|
groupTeams = append(groupTeams, groupTeam)
|
||||||
}
|
}
|
||||||
@@ -929,6 +938,7 @@ func testGetAllGroupSyncablesByGroup(t *testing.T, ss store.Store) {
|
|||||||
present := false
|
present := false
|
||||||
for _, dbGroupTeam := range d1 {
|
for _, dbGroupTeam := range d1 {
|
||||||
if dbGroupTeam.GroupId == expectedGroupTeam.GroupId && dbGroupTeam.SyncableId == expectedGroupTeam.SyncableId {
|
if dbGroupTeam.GroupId == expectedGroupTeam.GroupId && dbGroupTeam.SyncableId == expectedGroupTeam.SyncableId {
|
||||||
|
require.True(t, dbGroupTeam.SchemeAdmin)
|
||||||
present = true
|
present = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1720,6 +1730,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
DisplayName: "group-1",
|
DisplayName: "group-1",
|
||||||
RemoteId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
Source: model.GroupSourceLdap,
|
Source: model.GroupSourceLdap,
|
||||||
|
// SchemeAdmin: model.NewBool(false),
|
||||||
})
|
})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
@@ -1728,6 +1739,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
DisplayName: "group-2",
|
DisplayName: "group-2",
|
||||||
RemoteId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
Source: model.GroupSourceLdap,
|
Source: model.GroupSourceLdap,
|
||||||
|
// SchemeAdmin: model.NewBool(false),
|
||||||
})
|
})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
@@ -1758,6 +1770,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
DisplayName: "group-3",
|
DisplayName: "group-3",
|
||||||
RemoteId: model.NewId(),
|
RemoteId: model.NewId(),
|
||||||
Source: model.GroupSourceLdap,
|
Source: model.GroupSourceLdap,
|
||||||
|
// SchemeAdmin: model.NewBool(false),
|
||||||
})
|
})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
@@ -1801,12 +1814,16 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
group2WithMemberCount := *group2
|
group2WithMemberCount := *group2
|
||||||
group2WithMemberCount.MemberCount = model.NewInt(0)
|
group2WithMemberCount.MemberCount = model.NewInt(0)
|
||||||
|
|
||||||
|
group1WSA := &model.GroupWithSchemeAdmin{Group: *group1, SchemeAdmin: model.NewBool(false)}
|
||||||
|
group2WSA := &model.GroupWithSchemeAdmin{Group: *group2, SchemeAdmin: model.NewBool(false)}
|
||||||
|
group3WSA := &model.GroupWithSchemeAdmin{Group: *group3, SchemeAdmin: model.NewBool(false)}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Name string
|
Name string
|
||||||
ChannelId string
|
ChannelId string
|
||||||
Page int
|
Page int
|
||||||
PerPage int
|
PerPage int
|
||||||
Result []*model.Group
|
Result []*model.GroupWithSchemeAdmin
|
||||||
Opts model.GroupSearchOpts
|
Opts model.GroupSearchOpts
|
||||||
TotalCount *int64
|
TotalCount *int64
|
||||||
}{
|
}{
|
||||||
@@ -1816,7 +1833,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{group1, group2},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA, group2WSA},
|
||||||
TotalCount: model.NewInt64(2),
|
TotalCount: model.NewInt64(2),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1825,7 +1842,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 1,
|
PerPage: 1,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Get second Group for Channel1 with page 1 with 1 element",
|
Name: "Get second Group for Channel1 with page 1 with 1 element",
|
||||||
@@ -1833,7 +1850,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PerPage: 1,
|
PerPage: 1,
|
||||||
Result: []*model.Group{group2},
|
Result: []*model.GroupWithSchemeAdmin{group2WSA},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Get third Group for Channel2",
|
Name: "Get third Group for Channel2",
|
||||||
@@ -1841,7 +1858,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{group3},
|
Result: []*model.GroupWithSchemeAdmin{group3WSA},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Get empty Groups for a fake id",
|
Name: "Get empty Groups for a fake id",
|
||||||
@@ -1849,7 +1866,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{},
|
Result: []*model.GroupWithSchemeAdmin{},
|
||||||
TotalCount: model.NewInt64(0),
|
TotalCount: model.NewInt64(0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1858,7 +1875,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: string([]rune(group1.Name)[2:10])}, // very low change of a name collision
|
Opts: model.GroupSearchOpts{Q: string([]rune(group1.Name)[2:10])}, // very low change of a name collision
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
TotalCount: model.NewInt64(1),
|
TotalCount: model.NewInt64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1867,7 +1884,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: "rouP-1"},
|
Opts: model.GroupSearchOpts{Q: "rouP-1"},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
TotalCount: model.NewInt64(1),
|
TotalCount: model.NewInt64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1876,7 +1893,7 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: "roUp-"},
|
Opts: model.GroupSearchOpts{Q: "roUp-"},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1, group2},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA, group2WSA},
|
||||||
TotalCount: model.NewInt64(2),
|
TotalCount: model.NewInt64(2),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1885,7 +1902,10 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{IncludeMemberCount: true},
|
Opts: model.GroupSearchOpts{IncludeMemberCount: true},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 2,
|
PerPage: 2,
|
||||||
Result: []*model.Group{&group1WithMemberCount, &group2WithMemberCount},
|
Result: []*model.GroupWithSchemeAdmin{
|
||||||
|
{Group: group1WithMemberCount, SchemeAdmin: model.NewBool(false)},
|
||||||
|
{Group: group2WithMemberCount, SchemeAdmin: model.NewBool(false)},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2015,13 +2035,17 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
group2WithMemberCount := *group2
|
group2WithMemberCount := *group2
|
||||||
group2WithMemberCount.MemberCount = model.NewInt(0)
|
group2WithMemberCount.MemberCount = model.NewInt(0)
|
||||||
|
|
||||||
|
group1WSA := &model.GroupWithSchemeAdmin{Group: *group1, SchemeAdmin: model.NewBool(false)}
|
||||||
|
group2WSA := &model.GroupWithSchemeAdmin{Group: *group2, SchemeAdmin: model.NewBool(false)}
|
||||||
|
group3WSA := &model.GroupWithSchemeAdmin{Group: *group3, SchemeAdmin: model.NewBool(false)}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Name string
|
Name string
|
||||||
TeamId string
|
TeamId string
|
||||||
Page int
|
Page int
|
||||||
PerPage int
|
PerPage int
|
||||||
Opts model.GroupSearchOpts
|
Opts model.GroupSearchOpts
|
||||||
Result []*model.Group
|
Result []*model.GroupWithSchemeAdmin
|
||||||
TotalCount *int64
|
TotalCount *int64
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -2030,7 +2054,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{group1, group2},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA, group2WSA},
|
||||||
TotalCount: model.NewInt64(2),
|
TotalCount: model.NewInt64(2),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2039,7 +2063,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 1,
|
PerPage: 1,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Get second Group for Team1 with page 1 with 1 element",
|
Name: "Get second Group for Team1 with page 1 with 1 element",
|
||||||
@@ -2047,7 +2071,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PerPage: 1,
|
PerPage: 1,
|
||||||
Result: []*model.Group{group2},
|
Result: []*model.GroupWithSchemeAdmin{group2WSA},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Get third Group for Team2",
|
Name: "Get third Group for Team2",
|
||||||
@@ -2055,7 +2079,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{group3},
|
Result: []*model.GroupWithSchemeAdmin{group3WSA},
|
||||||
TotalCount: model.NewInt64(1),
|
TotalCount: model.NewInt64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2064,7 +2088,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{},
|
Opts: model.GroupSearchOpts{},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 60,
|
PerPage: 60,
|
||||||
Result: []*model.Group{},
|
Result: []*model.GroupWithSchemeAdmin{},
|
||||||
TotalCount: model.NewInt64(0),
|
TotalCount: model.NewInt64(0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2073,7 +2097,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: string([]rune(group1.Name)[2:10])}, // very low change of a name collision
|
Opts: model.GroupSearchOpts{Q: string([]rune(group1.Name)[2:10])}, // very low change of a name collision
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
TotalCount: model.NewInt64(1),
|
TotalCount: model.NewInt64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2082,7 +2106,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: "rouP-1"},
|
Opts: model.GroupSearchOpts{Q: "rouP-1"},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA},
|
||||||
TotalCount: model.NewInt64(1),
|
TotalCount: model.NewInt64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2091,7 +2115,7 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{Q: "roUp-"},
|
Opts: model.GroupSearchOpts{Q: "roUp-"},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 100,
|
PerPage: 100,
|
||||||
Result: []*model.Group{group1, group2},
|
Result: []*model.GroupWithSchemeAdmin{group1WSA, group2WSA},
|
||||||
TotalCount: model.NewInt64(2),
|
TotalCount: model.NewInt64(2),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2100,7 +2124,10 @@ func testGetGroupsByTeam(t *testing.T, ss store.Store) {
|
|||||||
Opts: model.GroupSearchOpts{IncludeMemberCount: true},
|
Opts: model.GroupSearchOpts{IncludeMemberCount: true},
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PerPage: 2,
|
PerPage: 2,
|
||||||
Result: []*model.Group{&group1WithMemberCount, &group2WithMemberCount},
|
Result: []*model.GroupWithSchemeAdmin{
|
||||||
|
{Group: group1WithMemberCount, SchemeAdmin: model.NewBool(false)},
|
||||||
|
{Group: group2WithMemberCount, SchemeAdmin: model.NewBool(false)},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2760,3 +2787,623 @@ func groupTestGetMemberCount(t *testing.T, ss store.Store) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, int64(1), count)
|
require.Equal(t, int64(1), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func groupTestAdminRoleGroupsForSyncableMemberChannel(t *testing.T, ss store.Store) {
|
||||||
|
user := &model.User{
|
||||||
|
Email: MakeEmail(),
|
||||||
|
Username: model.NewId(),
|
||||||
|
}
|
||||||
|
user, err := ss.User().Save(user)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group1 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group1, err = ss.Group().Create(group1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group2 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group2, err = ss.Group().Create(group2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group2.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
channel := &model.Channel{
|
||||||
|
TeamId: model.NewId(),
|
||||||
|
DisplayName: "A Name",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.CHANNEL_OPEN,
|
||||||
|
}
|
||||||
|
channel, err = ss.Channel().Save(channel, 9999)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: channel.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
GroupId: group1.Id,
|
||||||
|
SchemeAdmin: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
groupSyncable2, err := ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: channel.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
GroupId: group2.Id,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// User is a member of both groups but only one is SchmeAdmin: true
|
||||||
|
actualGroupIDs, err := ss.Group().AdminRoleGroupsForSyncableMember(user.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group1.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Update the second group syncable to be SchemeAdmin: true and both groups should be returned
|
||||||
|
groupSyncable2.SchemeAdmin = true
|
||||||
|
_, err = ss.Group().UpdateGroupSyncable(groupSyncable2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group1.Id, group2.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Deleting membership from group should stop the group from being returned
|
||||||
|
_, err = ss.Group().DeleteMember(group1.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group2.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Deleting group syncable should stop it being returned
|
||||||
|
_, err = ss.Group().DeleteGroupSyncable(group2.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{}, actualGroupIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupTestAdminRoleGroupsForSyncableMemberTeam(t *testing.T, ss store.Store) {
|
||||||
|
user := &model.User{
|
||||||
|
Email: MakeEmail(),
|
||||||
|
Username: model.NewId(),
|
||||||
|
}
|
||||||
|
user, err := ss.User().Save(user)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group1 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group1, err = ss.Group().Create(group1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group2 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group2, err = ss.Group().Create(group2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group2.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
team := &model.Team{
|
||||||
|
DisplayName: "A Name",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.CHANNEL_OPEN,
|
||||||
|
}
|
||||||
|
team, err = ss.Team().Save(team)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: team.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
GroupId: group1.Id,
|
||||||
|
SchemeAdmin: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
groupSyncable2, err := ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: team.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
GroupId: group2.Id,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// User is a member of both groups but only one is SchmeAdmin: true
|
||||||
|
actualGroupIDs, err := ss.Group().AdminRoleGroupsForSyncableMember(user.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group1.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Update the second group syncable to be SchemeAdmin: true and both groups should be returned
|
||||||
|
groupSyncable2.SchemeAdmin = true
|
||||||
|
_, err = ss.Group().UpdateGroupSyncable(groupSyncable2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group1.Id, group2.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Deleting membership from group should stop the group from being returned
|
||||||
|
_, err = ss.Group().DeleteMember(group1.Id, user.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{group2.Id}, actualGroupIDs)
|
||||||
|
|
||||||
|
// Deleting group syncable should stop it being returned
|
||||||
|
_, err = ss.Group().DeleteGroupSyncable(group2.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualGroupIDs, err = ss.Group().AdminRoleGroupsForSyncableMember(user.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{}, actualGroupIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupTestPermittedSyncableAdminsTeam(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)
|
||||||
|
|
||||||
|
group1 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group1, err = ss.Group().Create(group1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group2 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group2, err = ss.Group().Create(group2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group2.Id, user3.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
team := &model.Team{
|
||||||
|
DisplayName: "A Name",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.CHANNEL_OPEN,
|
||||||
|
}
|
||||||
|
team, err = ss.Team().Save(team)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: team.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
GroupId: group1.Id,
|
||||||
|
SchemeAdmin: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
groupSyncable2, err := ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: team.Id,
|
||||||
|
Type: model.GroupSyncableTypeTeam,
|
||||||
|
GroupId: group2.Id,
|
||||||
|
SchemeAdmin: false,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// group 1's users are returned because groupsyncable 2 has SchemeAdmin false.
|
||||||
|
actualUserIDs, err := ss.Group().PermittedSyncableAdmins(team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user2.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// update groupsyncable 2 to be SchemeAdmin true
|
||||||
|
groupSyncable2.SchemeAdmin = true
|
||||||
|
_, err = ss.Group().UpdateGroupSyncable(groupSyncable2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// group 2's users are now included in return value
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user2.Id, user3.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// deleted group member should not be included
|
||||||
|
ss.Group().DeleteMember(group1.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user3.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// deleted group syncable no longer includes group members
|
||||||
|
_, err = ss.Group().DeleteGroupSyncable(group1.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(team.Id, model.GroupSyncableTypeTeam)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user3.Id}, actualUserIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupTestPermittedSyncableAdminsChannel(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)
|
||||||
|
|
||||||
|
group1 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group1, err = ss.Group().Create(group1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user1.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
_, err = ss.Group().UpsertMember(group1.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
group2 := &model.Group{
|
||||||
|
Name: model.NewId(),
|
||||||
|
DisplayName: model.NewId(),
|
||||||
|
Source: model.GroupSourceLdap,
|
||||||
|
Description: model.NewId(),
|
||||||
|
RemoteId: model.NewId(),
|
||||||
|
}
|
||||||
|
group2, err = ss.Group().Create(group2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().UpsertMember(group2.Id, user3.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
channel := &model.Channel{
|
||||||
|
TeamId: model.NewId(),
|
||||||
|
DisplayName: "A Name",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.CHANNEL_OPEN,
|
||||||
|
}
|
||||||
|
channel, err = ss.Channel().Save(channel, 9999)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: channel.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
GroupId: group1.Id,
|
||||||
|
SchemeAdmin: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
groupSyncable2, err := ss.Group().CreateGroupSyncable(&model.GroupSyncable{
|
||||||
|
AutoAdd: true,
|
||||||
|
SyncableId: channel.Id,
|
||||||
|
Type: model.GroupSyncableTypeChannel,
|
||||||
|
GroupId: group2.Id,
|
||||||
|
SchemeAdmin: false,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// group 1's users are returned because groupsyncable 2 has SchemeAdmin false.
|
||||||
|
actualUserIDs, err := ss.Group().PermittedSyncableAdmins(channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user2.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// update groupsyncable 2 to be SchemeAdmin true
|
||||||
|
groupSyncable2.SchemeAdmin = true
|
||||||
|
_, err = ss.Group().UpdateGroupSyncable(groupSyncable2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// group 2's users are now included in return value
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user2.Id, user3.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// deleted group member should not be included
|
||||||
|
ss.Group().DeleteMember(group1.Id, user2.Id)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user1.Id, user3.Id}, actualUserIDs)
|
||||||
|
|
||||||
|
// deleted group syncable no longer includes group members
|
||||||
|
_, err = ss.Group().DeleteGroupSyncable(group1.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
actualUserIDs, err = ss.Group().PermittedSyncableAdmins(channel.Id, model.GroupSyncableTypeChannel)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.ElementsMatch(t, []string{user3.Id}, actualUserIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupTestpUpdateMembersRoleTeam(t *testing.T, ss store.Store) {
|
||||||
|
team := &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,
|
||||||
|
}
|
||||||
|
team, err := ss.Team().Save(team)
|
||||||
|
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)
|
||||||
|
|
||||||
|
user4 := &model.User{
|
||||||
|
Email: MakeEmail(),
|
||||||
|
Username: model.NewId(),
|
||||||
|
}
|
||||||
|
user4, err = ss.User().Save(user4)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
for _, user := range []*model.User{user1, user2, user3} {
|
||||||
|
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: user.Id}, 9999)
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: user4.Id, SchemeGuest: true}, 9999)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
testName string
|
||||||
|
inUserIDs []string
|
||||||
|
targetSchemeAdminValue bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Given users are admins",
|
||||||
|
[]string{user1.Id, user2.Id},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Given users are members",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Non-given users are admins",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Non-given users are members",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
includes := func(list []string, item string) bool {
|
||||||
|
for _, it := range list {
|
||||||
|
if it == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.testName, func(t *testing.T) {
|
||||||
|
err = ss.Team().UpdateMembersRole(team.Id, tt.inUserIDs)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
members, err := ss.Team().GetMembers(team.Id, 0, 100, nil)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.GreaterOrEqual(t, len(members), 4) // sanity check for team membership
|
||||||
|
|
||||||
|
for _, member := range members {
|
||||||
|
if includes(tt.inUserIDs, member.UserId) {
|
||||||
|
require.True(t, member.SchemeAdmin)
|
||||||
|
} else {
|
||||||
|
require.False(t, member.SchemeAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure guest account never changes.
|
||||||
|
if member.UserId == user4.Id {
|
||||||
|
require.False(t, member.SchemeUser)
|
||||||
|
require.False(t, member.SchemeAdmin)
|
||||||
|
require.True(t, member.SchemeGuest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func groupTestpUpdateMembersRoleChannel(t *testing.T, ss store.Store) {
|
||||||
|
channel := &model.Channel{
|
||||||
|
TeamId: model.NewId(),
|
||||||
|
DisplayName: "A Name",
|
||||||
|
Name: model.NewId(),
|
||||||
|
Type: model.CHANNEL_OPEN, // Query does not look at type so this shouldn't matter.
|
||||||
|
}
|
||||||
|
channel, err := ss.Channel().Save(channel, 9999)
|
||||||
|
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)
|
||||||
|
|
||||||
|
user4 := &model.User{
|
||||||
|
Email: MakeEmail(),
|
||||||
|
Username: model.NewId(),
|
||||||
|
}
|
||||||
|
user4, err = ss.User().Save(user4)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
for _, user := range []*model.User{user1, user2, user3} {
|
||||||
|
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||||
|
ChannelId: channel.Id,
|
||||||
|
UserId: user.Id,
|
||||||
|
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||||
|
ChannelId: channel.Id,
|
||||||
|
UserId: user4.Id,
|
||||||
|
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||||
|
SchemeGuest: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
testName string
|
||||||
|
inUserIDs []string
|
||||||
|
targetSchemeAdminValue bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Given users are admins",
|
||||||
|
[]string{user1.Id, user2.Id},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Given users are members",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Non-given users are admins",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Non-given users are members",
|
||||||
|
[]string{user2.Id},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
includes := func(list []string, item string) bool {
|
||||||
|
for _, it := range list {
|
||||||
|
if it == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.testName, func(t *testing.T) {
|
||||||
|
err = ss.Channel().UpdateMembersRole(channel.Id, tt.inUserIDs)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
members, err := ss.Channel().GetMembers(channel.Id, 0, 100)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.GreaterOrEqual(t, len(*members), 4) // sanity check for channel membership
|
||||||
|
|
||||||
|
for _, member := range *members {
|
||||||
|
if includes(tt.inUserIDs, member.UserId) {
|
||||||
|
require.True(t, member.SchemeAdmin)
|
||||||
|
} else {
|
||||||
|
require.False(t, member.SchemeAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure guest account never changes.
|
||||||
|
if member.UserId == user4.Id {
|
||||||
|
require.False(t, member.SchemeUser)
|
||||||
|
require.False(t, member.SchemeAdmin)
|
||||||
|
require.True(t, member.SchemeGuest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1707,6 +1707,22 @@ func (_m *ChannelStore) UpdateMember(member *model.ChannelMember) (*model.Channe
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateMembersRole provides a mock function with given fields: channelID, userIDs
|
||||||
|
func (_m *ChannelStore) UpdateMembersRole(channelID string, userIDs []string) *model.AppError {
|
||||||
|
ret := _m.Called(channelID, userIDs)
|
||||||
|
|
||||||
|
var r0 *model.AppError
|
||||||
|
if rf, ok := ret.Get(0).(func(string, []string) *model.AppError); ok {
|
||||||
|
r0 = rf(channelID, userIDs)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// UserBelongsToChannels provides a mock function with given fields: userId, channelIds
|
// UserBelongsToChannels provides a mock function with given fields: userId, channelIds
|
||||||
func (_m *ChannelStore) UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError) {
|
func (_m *ChannelStore) UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError) {
|
||||||
ret := _m.Called(userId, channelIds)
|
ret := _m.Called(userId, channelIds)
|
||||||
|
|||||||
@@ -14,6 +14,31 @@ type GroupStore struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdminRoleGroupsForSyncableMember provides a mock function with given fields: userID, syncableID, syncableType
|
||||||
|
func (_m *GroupStore) AdminRoleGroupsForSyncableMember(userID string, syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
ret := _m.Called(userID, syncableID, syncableType)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string, model.GroupSyncableType) []string); ok {
|
||||||
|
r0 = rf(userID, syncableID, syncableType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func(string, string, model.GroupSyncableType) *model.AppError); ok {
|
||||||
|
r1 = rf(userID, syncableID, syncableType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelMembersMinusGroupMembers provides a mock function with given fields: channelID, groupIDs, page, perPage
|
// ChannelMembersMinusGroupMembers provides a mock function with given fields: channelID, groupIDs, page, perPage
|
||||||
func (_m *GroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
func (_m *GroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
||||||
ret := _m.Called(channelID, groupIDs, page, perPage)
|
ret := _m.Called(channelID, groupIDs, page, perPage)
|
||||||
@@ -532,15 +557,15 @@ func (_m *GroupStore) GetGroups(page int, perPage int, opts model.GroupSearchOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetGroupsByChannel provides a mock function with given fields: channelId, opts
|
// GetGroupsByChannel provides a mock function with given fields: channelId, opts
|
||||||
func (_m *GroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (_m *GroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
ret := _m.Called(channelId, opts)
|
ret := _m.Called(channelId, opts)
|
||||||
|
|
||||||
var r0 []*model.Group
|
var r0 []*model.GroupWithSchemeAdmin
|
||||||
if rf, ok := ret.Get(0).(func(string, model.GroupSearchOpts) []*model.Group); ok {
|
if rf, ok := ret.Get(0).(func(string, model.GroupSearchOpts) []*model.GroupWithSchemeAdmin); ok {
|
||||||
r0 = rf(channelId, opts)
|
r0 = rf(channelId, opts)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]*model.Group)
|
r0 = ret.Get(0).([]*model.GroupWithSchemeAdmin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,15 +582,15 @@ func (_m *GroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetGroupsByTeam provides a mock function with given fields: teamId, opts
|
// GetGroupsByTeam provides a mock function with given fields: teamId, opts
|
||||||
func (_m *GroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (_m *GroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
ret := _m.Called(teamId, opts)
|
ret := _m.Called(teamId, opts)
|
||||||
|
|
||||||
var r0 []*model.Group
|
var r0 []*model.GroupWithSchemeAdmin
|
||||||
if rf, ok := ret.Get(0).(func(string, model.GroupSearchOpts) []*model.Group); ok {
|
if rf, ok := ret.Get(0).(func(string, model.GroupSearchOpts) []*model.GroupWithSchemeAdmin); ok {
|
||||||
r0 = rf(teamId, opts)
|
r0 = rf(teamId, opts)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]*model.Group)
|
r0 = ret.Get(0).([]*model.GroupWithSchemeAdmin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,6 +695,31 @@ func (_m *GroupStore) PermanentDeleteMembersByUser(userId string) *model.AppErro
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PermittedSyncableAdmins provides a mock function with given fields: syncableID, syncableType
|
||||||
|
func (_m *GroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
ret := _m.Called(syncableID, syncableType)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(string, model.GroupSyncableType) []string); ok {
|
||||||
|
r0 = rf(syncableID, syncableType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func(string, model.GroupSyncableType) *model.AppError); ok {
|
||||||
|
r1 = rf(syncableID, syncableType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// TeamMembersMinusGroupMembers provides a mock function with given fields: teamID, groupIDs, page, perPage
|
// TeamMembersMinusGroupMembers provides a mock function with given fields: teamID, groupIDs, page, perPage
|
||||||
func (_m *GroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
func (_m *GroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
||||||
ret := _m.Called(teamID, groupIDs, page, perPage)
|
ret := _m.Called(teamID, groupIDs, page, perPage)
|
||||||
|
|||||||
@@ -1056,6 +1056,22 @@ func (_m *TeamStore) UpdateMember(member *model.TeamMember) (*model.TeamMember,
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateMembersRole provides a mock function with given fields: teamID, userIDs
|
||||||
|
func (_m *TeamStore) UpdateMembersRole(teamID string, userIDs []string) *model.AppError {
|
||||||
|
ret := _m.Called(teamID, userIDs)
|
||||||
|
|
||||||
|
var r0 *model.AppError
|
||||||
|
if rf, ok := ret.Get(0).(func(string, []string) *model.AppError); ok {
|
||||||
|
r0 = rf(teamID, userIDs)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// UserBelongsToTeams provides a mock function with given fields: userId, teamIds
|
// UserBelongsToTeams provides a mock function with given fields: userId, teamIds
|
||||||
func (_m *TeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool, *model.AppError) {
|
func (_m *TeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool, *model.AppError) {
|
||||||
ret := _m.Called(userId, teamIds)
|
ret := _m.Called(userId, teamIds)
|
||||||
|
|||||||
@@ -1736,6 +1736,22 @@ func (s *TimerLayerChannelStore) UpdateMember(member *model.ChannelMember) (*mod
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerChannelStore) UpdateMembersRole(channelID string, userIDs []string) *model.AppError {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
resultVar0 := s.ChannelStore.UpdateMembersRole(channelID, userIDs)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if resultVar0 == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.UpdateMembersRole", success, elapsed)
|
||||||
|
}
|
||||||
|
return resultVar0
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerChannelStore) UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError) {
|
func (s *TimerLayerChannelStore) UserBelongsToChannels(userId string, channelIds []string) (bool, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
@@ -2520,6 +2536,22 @@ func (s *TimerLayerFileInfoStore) Save(info *model.FileInfo) (*model.FileInfo, *
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerGroupStore) AdminRoleGroupsForSyncableMember(userID string, syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
resultVar0, resultVar1 := s.GroupStore.AdminRoleGroupsForSyncableMember(userID, syncableID, syncableType)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if resultVar1 == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("GroupStore.AdminRoleGroupsForSyncableMember", success, elapsed)
|
||||||
|
}
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerGroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
func (s *TimerLayerGroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
@@ -2856,7 +2888,7 @@ func (s *TimerLayerGroupStore) GetGroups(page int, perPage int, opts model.Group
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (s *TimerLayerGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
resultVar0, resultVar1 := s.GroupStore.GetGroupsByChannel(channelId, opts)
|
resultVar0, resultVar1 := s.GroupStore.GetGroupsByChannel(channelId, opts)
|
||||||
@@ -2872,7 +2904,7 @@ func (s *TimerLayerGroupStore) GetGroupsByChannel(channelId string, opts model.G
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
|
func (s *TimerLayerGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
resultVar0, resultVar1 := s.GroupStore.GetGroupsByTeam(teamId, opts)
|
resultVar0, resultVar1 := s.GroupStore.GetGroupsByTeam(teamId, opts)
|
||||||
@@ -2952,6 +2984,22 @@ func (s *TimerLayerGroupStore) PermanentDeleteMembersByUser(userId string) *mode
|
|||||||
return resultVar0
|
return resultVar0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerGroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
resultVar0, resultVar1 := s.GroupStore.PermittedSyncableAdmins(syncableID, syncableType)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if resultVar1 == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("GroupStore.PermittedSyncableAdmins", success, elapsed)
|
||||||
|
}
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerGroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
func (s *TimerLayerGroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page int, perPage int) ([]*model.UserWithGroups, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
@@ -5880,6 +5928,22 @@ func (s *TimerLayerTeamStore) UpdateMember(member *model.TeamMember) (*model.Tea
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerTeamStore) UpdateMembersRole(teamID string, userIDs []string) *model.AppError {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
resultVar0 := s.TeamStore.UpdateMembersRole(teamID, userIDs)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if resultVar0 == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("TeamStore.UpdateMembersRole", success, elapsed)
|
||||||
|
}
|
||||||
|
return resultVar0
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerTeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool, *model.AppError) {
|
func (s *TimerLayerTeamStore) UserBelongsToTeams(userId string, teamIds []string) (bool, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user