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
@@ -971,6 +971,16 @@ func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMem
|
||||
SchemeGuest: 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 {
|
||||
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)
|
||||
|
||||
@@ -1161,3 +1161,55 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
||||
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()
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -182,7 +182,7 @@ func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) (
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -313,3 +313,18 @@ func (a *App) ChannelMembersMinusGroupMembers(channelID string, groupIDs []strin
|
||||
}
|
||||
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)
|
||||
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)
|
||||
require.Nil(t, err)
|
||||
@@ -261,7 +262,8 @@ func TestGetGroupsByTeam(t *testing.T) {
|
||||
|
||||
groups, _, err := th.App.GetGroupsByTeam(th.BasicTeam.Id, model.GroupSearchOpts{})
|
||||
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{})
|
||||
require.Nil(t, err)
|
||||
@@ -277,3 +279,55 @@ func TestGetGroups(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
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(),
|
||||
}
|
||||
|
||||
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 {
|
||||
tm.SchemeAdmin = true
|
||||
}
|
||||
|
||||
@@ -639,7 +639,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
||||
ruser, _ := th.App.CreateUser(&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.Nil(t, err, "Should return no error")
|
||||
})
|
||||
@@ -651,7 +652,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
||||
|
||||
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.Nil(t, err, "Should return no error")
|
||||
})
|
||||
@@ -664,7 +666,8 @@ func TestJoinUserToTeam(t *testing.T) {
|
||||
th.App.joinUserToTeam(team, ruser)
|
||||
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.Nil(t, err, "Should return no error")
|
||||
})
|
||||
@@ -679,7 +682,7 @@ func TestJoinUserToTeam(t *testing.T) {
|
||||
defer th.App.PermanentDeleteUser(&user2)
|
||||
th.App.joinUserToTeam(team, ruser1)
|
||||
|
||||
_, _, err := th.App.joinUserToTeam(team, ruser2)
|
||||
_, _, err = th.App.joinUserToTeam(team, ruser2)
|
||||
require.NotNil(t, err, "Should fail")
|
||||
})
|
||||
|
||||
@@ -697,9 +700,50 @@ func TestJoinUserToTeam(t *testing.T) {
|
||||
th.App.LeaveTeam(team, ruser1, ruser1.Id)
|
||||
th.App.joinUserToTeam(team, ruser2)
|
||||
|
||||
_, _, err := th.App.joinUserToTeam(team, ruser1)
|
||||
_, _, err = th.App.joinUserToTeam(team, ruser1)
|
||||
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) {
|
||||
|
||||
Ссылка в новой задаче
Block a user