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
Этот коммит содержится в:
Martin Kraft
2020-01-10 12:19:39 -05:00
коммит произвёл catalintomai
родитель 04430041a8
Коммит 605040c597
21 изменённых файлов: 1207 добавлений и 70 удалений

Просмотреть файл

@@ -2838,3 +2838,25 @@ func (s SqlChannelStore) UserBelongsToChannels(userId string, channelIds []strin
}
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.CreateColumnIfNotExistsNoDefault("Channels", "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) {
@@ -512,6 +514,7 @@ func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableTy
Type: syncableType,
TeamDisplayName: result.TeamDisplayName,
TeamType: result.TeamType,
SchemeAdmin: result.SchemeAdmin,
}
groupSyncables = append(groupSyncables, groupSyncable)
}
@@ -550,6 +553,7 @@ func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableTy
TeamDisplayName: result.TeamDisplayName,
TeamType: result.TeamType,
TeamID: result.TeamID,
SchemeAdmin: result.SchemeAdmin,
}
groupSyncables = append(groupSyncables, groupSyncable)
}
@@ -784,7 +788,7 @@ func (s *SqlGroupStore) CountGroupsByChannel(channelId string, opts model.GroupS
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)
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)
}
var groups []*model.Group
var groups []*model.GroupWithSchemeAdmin
_, err = s.GetReplica().Select(&groups, queryString, args...)
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 {
selectStrs := map[selectType]string{
selectGroups: "ug.*",
selectGroups: "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin",
selectCountGroups: "COUNT(*)",
}
@@ -883,7 +887,7 @@ func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t
if opts.IncludeMemberCount && t == selectGroups {
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").
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)).
@@ -919,7 +923,7 @@ func (s *SqlGroupStore) CountGroupsByTeam(teamId string, opts model.GroupSearchO
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)
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)
}
var groups []*model.Group
var groups []*model.GroupWithSchemeAdmin
_, err = s.GetReplica().Select(&groups, queryString, args...)
if err != nil {
@@ -1164,3 +1168,46 @@ func (s *SqlGroupStore) CountChannelMembersMinusGroupMembers(channelID string, g
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
}
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 {
if restrictions == nil {
return query

Просмотреть файл

@@ -754,6 +754,12 @@ func upgradeDatabaseToVersion520(sqlStore SqlStore) {
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)
// }
}