Team/Channel members bulk save/update/delete (#14053)

* Members Save Multiple

* Multiple Channel Members implemented

* Working version with member multi save and multi update

* Adding tests to the save multiple team members store methods

* Tests passing for SaveMember

* Adding remove members tests

* Working on channel store tests

* More work on testing properly SaveMember and SaveMultipleMembers on channels

* More work on testing properly SaveMember and SaveMultipleMembers on teams

* Adding tests for update multiple members for team

* Adding tests for update multiple members for channel

* Fixing some tets

* Fixing tests

* Fixing tests

* Fixing i18n

* Addressing govet problems

* Addressing govet problems

* Addressing govet problems

* Addressing govet problems

* Addressing PR comments (and removing TODO)

* Addressing PR comments

* Fixed broken test

* Removing unnecesary i18n translation string
Этот коммит содержится в:
Jesús Espino
2020-03-27 13:29:17 +01:00
коммит произвёл GitHub
родитель d2848cc167
Коммит cfe65a33a5
16 изменённых файлов: 5248 добавлений и 353 удалений

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

@@ -87,94 +87,154 @@ type channelMemberWithSchemeRoles struct {
ChannelSchemeDefaultAdminRole sql.NullString
}
func channelMemberSliceColumns() []string {
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MentionCount", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
}
func channelMemberToSlice(member *model.ChannelMember) []interface{} {
resultSlice := []interface{}{}
resultSlice = append(resultSlice, member.ChannelId)
resultSlice = append(resultSlice, member.UserId)
resultSlice = append(resultSlice, member.ExplicitRoles)
resultSlice = append(resultSlice, member.LastViewedAt)
resultSlice = append(resultSlice, member.MsgCount)
resultSlice = append(resultSlice, member.MentionCount)
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
resultSlice = append(resultSlice, member.LastUpdateAt)
resultSlice = append(resultSlice, member.SchemeUser)
resultSlice = append(resultSlice, member.SchemeAdmin)
resultSlice = append(resultSlice, member.SchemeGuest)
return resultSlice
}
type channelMemberWithSchemeRolesList []channelMemberWithSchemeRoles
func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
var roles []string
var explicitRoles []string
func getChannelRoles(schemeGuest, schemeUser, schemeAdmin bool, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole, defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole string, roles []string) rolesInfo {
result := rolesInfo{
roles: []string{},
explicitRoles: []string{},
schemeGuest: schemeGuest,
schemeUser: schemeUser,
schemeAdmin: schemeAdmin,
}
// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
// and exclude them from ExplicitRoles field.
schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
for _, role := range strings.Fields(db.Roles) {
isImplicit := false
if role == model.CHANNEL_GUEST_ROLE_ID {
// We have an implicit role via the system scheme. Override the "schemeGuest" field to true.
schemeGuest = true
isImplicit = true
} else if role == model.CHANNEL_USER_ROLE_ID {
// We have an implicit role via the system scheme. Override the "schemeUser" field to true.
schemeUser = true
isImplicit = true
} else if role == model.CHANNEL_ADMIN_ROLE_ID {
// We have an implicit role via the system scheme.
schemeAdmin = true
isImplicit = true
// Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude
// them from ExplicitRoles field.
for _, role := range roles {
switch role {
case model.CHANNEL_GUEST_ROLE_ID:
result.schemeGuest = true
case model.CHANNEL_USER_ROLE_ID:
result.schemeUser = true
case model.CHANNEL_ADMIN_ROLE_ID:
result.schemeAdmin = true
default:
result.explicitRoles = append(result.explicitRoles, role)
result.roles = append(result.roles, role)
}
if !isImplicit {
explicitRoles = append(explicitRoles, role)
}
roles = append(roles, role)
}
// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
// them to the Roles field for backwards compatibility reasons.
var schemeImpliedRoles []string
if db.SchemeGuest.Valid && db.SchemeGuest.Bool {
if db.ChannelSchemeDefaultGuestRole.Valid && db.ChannelSchemeDefaultGuestRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultGuestRole.String)
} else if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String)
if result.schemeGuest {
if defaultChannelGuestRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelGuestRole)
} else if defaultTeamGuestRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamGuestRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_GUEST_ROLE_ID)
}
}
if db.SchemeUser.Valid && db.SchemeUser.Bool {
if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
if result.schemeUser {
if defaultChannelUserRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelUserRole)
} else if defaultTeamUserRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamUserRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
}
}
if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
if result.schemeAdmin {
if defaultChannelAdminRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelAdminRole)
} else if defaultTeamAdminRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamAdminRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
}
}
for _, impliedRole := range schemeImpliedRoles {
alreadyThere := false
for _, role := range roles {
for _, role := range result.roles {
if role == impliedRole {
alreadyThere = true
break
}
}
if !alreadyThere {
roles = append(roles, impliedRole)
result.roles = append(result.roles, impliedRole)
}
}
return result
}
func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
// and exclude them from ExplicitRoles field.
schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
defaultTeamGuestRole := ""
if db.TeamSchemeDefaultGuestRole.Valid {
defaultTeamGuestRole = db.TeamSchemeDefaultGuestRole.String
}
defaultTeamUserRole := ""
if db.TeamSchemeDefaultUserRole.Valid {
defaultTeamUserRole = db.TeamSchemeDefaultUserRole.String
}
defaultTeamAdminRole := ""
if db.TeamSchemeDefaultAdminRole.Valid {
defaultTeamAdminRole = db.TeamSchemeDefaultAdminRole.String
}
defaultChannelGuestRole := ""
if db.ChannelSchemeDefaultGuestRole.Valid {
defaultChannelGuestRole = db.ChannelSchemeDefaultGuestRole.String
}
defaultChannelUserRole := ""
if db.ChannelSchemeDefaultUserRole.Valid {
defaultChannelUserRole = db.ChannelSchemeDefaultUserRole.String
}
defaultChannelAdminRole := ""
if db.ChannelSchemeDefaultAdminRole.Valid {
defaultChannelAdminRole = db.ChannelSchemeDefaultAdminRole.String
}
rolesResult := getChannelRoles(
schemeGuest, schemeUser, schemeAdmin,
defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole,
defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole,
strings.Fields(db.Roles),
)
return &model.ChannelMember{
ChannelId: db.ChannelId,
UserId: db.UserId,
Roles: strings.Join(roles, " "),
Roles: strings.Join(rolesResult.roles, " "),
LastViewedAt: db.LastViewedAt,
MsgCount: db.MsgCount,
MentionCount: db.MentionCount,
NotifyProps: db.NotifyProps,
LastUpdateAt: db.LastUpdateAt,
SchemeAdmin: schemeAdmin,
SchemeUser: schemeUser,
SchemeGuest: schemeGuest,
ExplicitRoles: strings.Join(explicitRoles, " "),
SchemeAdmin: rolesResult.schemeAdmin,
SchemeUser: rolesResult.schemeUser,
SchemeGuest: rolesResult.schemeGuest,
ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
}
}
@@ -526,21 +586,15 @@ func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1
member1.ChannelId = newChannel.Id
member2.ChannelId = newChannel.Id
_, member1SaveErr := s.saveMemberT(transaction, member1)
member2SaveErr := member1SaveErr
var memberSaveErr *model.AppError
if member1.UserId != member2.UserId {
_, member2SaveErr = s.saveMemberT(transaction, member2)
_, memberSaveErr = s.saveMultipleMembersT(transaction, []*model.ChannelMember{member1, member2})
} else {
_, memberSaveErr = s.saveMemberT(transaction, member2)
}
if member1SaveErr != nil || member2SaveErr != nil {
details := ""
if member1SaveErr != nil {
details += "Member1Err: " + member1SaveErr.Message
}
if member2SaveErr != nil {
details += "Member2Err: " + member2SaveErr.Message
}
return nil, model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.add_members.app_error", nil, details, http.StatusInternalServerError)
if memberSaveErr != nil {
return nil, model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.add_members.app_error", nil, memberSaveErr.Error(), http.StatusInternalServerError)
}
if err := transaction.Commit(); err != nil {
@@ -1252,8 +1306,10 @@ var CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY = `
Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
`
func (s SqlChannelStore) SaveMember(member *model.ChannelMember) (*model.ChannelMember, *model.AppError) {
defer s.InvalidateAllChannelMembersForUser(member.UserId)
func (s SqlChannelStore) SaveMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, *model.AppError) {
for _, member := range members {
defer s.InvalidateAllChannelMembersForUser(member.UserId)
}
transaction, err := s.GetMaster().Begin()
if err != nil {
@@ -1261,7 +1317,7 @@ func (s SqlChannelStore) SaveMember(member *model.ChannelMember) (*model.Channel
}
defer finalizeTransaction(transaction)
newMember, appErr := s.saveMemberT(transaction, member)
newMembers, appErr := s.saveMultipleMembersT(transaction, members)
if appErr != nil {
return nil, appErr
}
@@ -1270,55 +1326,212 @@ func (s SqlChannelStore) SaveMember(member *model.ChannelMember) (*model.Channel
return nil, model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return newMember, nil
return newMembers, nil
}
func (s SqlChannelStore) SaveMember(member *model.ChannelMember) (*model.ChannelMember, *model.AppError) {
newMembers, appErr := s.SaveMultipleMembers([]*model.ChannelMember{member})
if appErr != nil {
return nil, appErr
}
return newMembers[0], nil
}
func (s SqlChannelStore) saveMultipleMembersT(transaction *gorp.Transaction, members []*model.ChannelMember) ([]*model.ChannelMember, *model.AppError) {
newChannelMembers := map[string]int{}
users := map[string]bool{}
for _, member := range members {
if val, ok := newChannelMembers[member.ChannelId]; val < 1 || !ok {
newChannelMembers[member.ChannelId] = 1
} else {
newChannelMembers[member.ChannelId]++
}
users[member.UserId] = true
member.PreSave()
if err := member.IsValid(); err != nil {
return nil, err
}
}
channels := []string{}
for channel := range newChannelMembers {
channels = append(channels, channel)
}
defaultChannelRolesByChannel := map[string]struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}{}
channelRolesQuery := s.getQueryBuilder().
Select(
"Channels.Id as Id",
"ChannelScheme.DefaultChannelGuestRole as Guest",
"ChannelScheme.DefaultChannelUserRole as User",
"ChannelScheme.DefaultChannelAdminRole as Admin",
).
From("Channels").
LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
Where(sq.Eq{"Channels.Id": channels})
channelRolesSql, channelRolesArgs, err := channelRolesQuery.ToSql()
if err != nil {
return nil, model.NewAppError("SqlChannelStore.SaveMultipleMembers", "store.sql_channel.save_multimple_members.channel_roles.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var defaultChannelsRoles []struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}
_, err = s.GetMaster().Select(&defaultChannelsRoles, channelRolesSql, channelRolesArgs...)
if err != nil {
return nil, model.NewAppError("SqlChannelStore.SaveMultipleMembers", "store.sql_channel.save_multimple_members.channel_roles_query.app_error", nil, err.Error(), http.StatusInternalServerError)
}
for _, defaultRoles := range defaultChannelsRoles {
defaultChannelRolesByChannel[defaultRoles.Id] = defaultRoles
}
defaultTeamRolesByChannel := map[string]struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}{}
teamRolesQuery := s.getQueryBuilder().
Select(
"Channels.Id as Id",
"TeamScheme.DefaultChannelGuestRole as Guest",
"TeamScheme.DefaultChannelUserRole as User",
"TeamScheme.DefaultChannelAdminRole as Admin",
).
From("Channels").
LeftJoin("Teams ON Teams.Id = Channels.TeamId").
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
Where(sq.Eq{"Channels.Id": channels})
teamRolesSql, teamRolesArgs, err := teamRolesQuery.ToSql()
if err != nil {
return nil, model.NewAppError("SqlChannelStore.SaveMultipleMembers", "store.sql_channel.save_multimple_members.team_roles.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var defaultTeamsRoles []struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}
_, err = s.GetMaster().Select(&defaultTeamsRoles, teamRolesSql, teamRolesArgs...)
if err != nil {
return nil, model.NewAppError("SqlChannelStore.SaveMultipleMembers", "store.sql_channel.save_multimple_members.team_roles_query.app_error", nil, err.Error(), http.StatusInternalServerError)
}
for _, defaultRoles := range defaultTeamsRoles {
defaultTeamRolesByChannel[defaultRoles.Id] = defaultRoles
}
query := s.getQueryBuilder().Insert("ChannelMembers").Columns(channelMemberSliceColumns()...)
for _, member := range members {
query = query.Values(channelMemberToSlice(member)...)
}
sql, args, err := query.ToSql()
if err != nil {
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
if _, err := s.GetMaster().Exec(sql, args...); err != nil {
if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey", "PRIMARY"}) {
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_channel.save_member.exists.app_error", nil, err.Error(), http.StatusBadRequest)
}
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
newMembers := []*model.ChannelMember{}
for _, member := range members {
defaultTeamGuestRole := defaultTeamRolesByChannel[member.ChannelId].Guest.String
defaultTeamUserRole := defaultTeamRolesByChannel[member.ChannelId].User.String
defaultTeamAdminRole := defaultTeamRolesByChannel[member.ChannelId].Admin.String
defaultChannelGuestRole := defaultChannelRolesByChannel[member.ChannelId].Guest.String
defaultChannelUserRole := defaultChannelRolesByChannel[member.ChannelId].User.String
defaultChannelAdminRole := defaultChannelRolesByChannel[member.ChannelId].Admin.String
rolesResult := getChannelRoles(
member.SchemeGuest, member.SchemeUser, member.SchemeAdmin,
defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole,
defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole,
strings.Fields(member.ExplicitRoles),
)
newMember := *member
newMember.SchemeGuest = rolesResult.schemeGuest
newMember.SchemeUser = rolesResult.schemeUser
newMember.SchemeAdmin = rolesResult.schemeAdmin
newMember.Roles = strings.Join(rolesResult.roles, " ")
newMember.ExplicitRoles = strings.Join(rolesResult.explicitRoles, " ")
newMembers = append(newMembers, &newMember)
}
return newMembers, nil
}
func (s SqlChannelStore) saveMemberT(transaction *gorp.Transaction, member *model.ChannelMember) (*model.ChannelMember, *model.AppError) {
member.PreSave()
if err := member.IsValid(); err != nil {
members, err := s.saveMultipleMembersT(transaction, []*model.ChannelMember{member})
if err != nil {
return nil, err
}
return members[0], nil
}
dbMember := NewChannelMemberFromModel(member)
func (s SqlChannelStore) UpdateMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, *model.AppError) {
for _, member := range members {
member.PreUpdate()
if err := transaction.Insert(dbMember); err != nil {
if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey"}) {
return nil, model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.exists.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
if err := member.IsValid(); err != nil {
return nil, err
}
return nil, model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
}
var retrievedMember channelMemberWithSchemeRoles
if err := transaction.SelectOne(&retrievedMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": dbMember.ChannelId, "UserId": dbMember.UserId}); err != nil {
if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
var transaction *gorp.Transaction
var err error
if transaction, err = s.GetMaster().Begin(); err != nil {
return nil, model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
}
defer finalizeTransaction(transaction)
updatedMembers := []*model.ChannelMember{}
for _, member := range members {
if _, err := transaction.Update(NewChannelMemberFromModel(member)); err != nil {
return nil, model.NewAppError("SqlChannelStore.UpdateMember", "store.sql_channel.update_member.app_error", nil, "channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
}
return nil, model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError)
// TODO: Get this out of the transaction when is possible
var dbMember channelMemberWithSchemeRoles
if err := transaction.SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
}
return nil, model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
}
updatedMembers = append(updatedMembers, dbMember.ToModel())
}
return retrievedMember.ToModel(), nil
if err := transaction.Commit(); err != nil {
return nil, model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return updatedMembers, nil
}
func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) (*model.ChannelMember, *model.AppError) {
member.PreUpdate()
if err := member.IsValid(); err != nil {
updatedMembers, err := s.UpdateMultipleMembers([]*model.ChannelMember{member})
if err != nil {
return nil, err
}
if _, err := s.GetMaster().Update(NewChannelMemberFromModel(member)); err != nil {
return nil, model.NewAppError("SqlChannelStore.UpdateMember", "store.sql_channel.update_member.app_error", nil, "channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
}
var dbMember channelMemberWithSchemeRoles
if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
}
return nil, model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
}
return dbMember.ToModel(), nil
return updatedMembers[0], nil
}
func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) (*model.ChannelMembers, *model.AppError) {
@@ -1606,14 +1819,26 @@ func (s SqlChannelStore) GetGuestCount(channelId string, allowFromCache bool) (i
return count, nil
}
func (s SqlChannelStore) RemoveMember(channelId string, userId string) *model.AppError {
_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId})
func (s SqlChannelStore) RemoveMembers(channelId string, userIds []string) *model.AppError {
query := s.getQueryBuilder().
Delete("ChannelMembers").
Where(sq.Eq{"ChannelId": channelId}).
Where(sq.Eq{"UserId": userIds})
sql, args, err := query.ToSql()
if err != nil {
return model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
return model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
}
_, err = s.GetMaster().Exec(sql, args...)
if err != nil {
return model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
}
return nil
}
func (s SqlChannelStore) RemoveMember(channelId string, userId string) *model.AppError {
return s.RemoveMembers(channelId, []string{userId})
}
func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) *model.AppError {
query := `
DELETE

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

@@ -154,7 +154,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) {
cm := db.ToModel()
assert.Equal(t, "channel_admin channel_user", cm.Roles)
assert.Equal(t, "channel_user channel_admin", cm.Roles)
assert.Equal(t, false, cm.SchemeGuest)
assert.Equal(t, true, cm.SchemeUser)
assert.Equal(t, true, cm.SchemeAdmin)
@@ -199,7 +199,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) {
cm := db.ToModel()
assert.Equal(t, "channel_user custom_role", cm.Roles)
assert.Equal(t, "custom_role channel_user", cm.Roles)
assert.Equal(t, false, cm.SchemeGuest)
assert.Equal(t, true, cm.SchemeUser)
assert.Equal(t, false, cm.SchemeAdmin)
@@ -222,7 +222,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) {
cm := db.ToModel()
assert.Equal(t, "channel_user channel_admin custom_role", cm.Roles)
assert.Equal(t, "custom_role channel_user channel_admin", cm.Roles)
assert.Equal(t, false, cm.SchemeGuest)
assert.Equal(t, true, cm.SchemeUser)
assert.Equal(t, true, cm.SchemeAdmin)

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

@@ -61,82 +61,125 @@ type teamMemberWithSchemeRoles struct {
type teamMemberWithSchemeRolesList []teamMemberWithSchemeRoles
func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember {
var roles []string
var explicitRoles []string
func teamMemberSliceColumns() []string {
return []string{"TeamId", "UserId", "Roles", "DeleteAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
}
func teamMemberToSlice(member *model.TeamMember) []interface{} {
resultSlice := []interface{}{}
resultSlice = append(resultSlice, member.TeamId)
resultSlice = append(resultSlice, member.UserId)
resultSlice = append(resultSlice, member.ExplicitRoles)
resultSlice = append(resultSlice, member.DeleteAt)
resultSlice = append(resultSlice, member.SchemeUser)
resultSlice = append(resultSlice, member.SchemeAdmin)
resultSlice = append(resultSlice, member.SchemeGuest)
return resultSlice
}
type rolesInfo struct {
roles []string
explicitRoles []string
schemeGuest bool
schemeUser bool
schemeAdmin bool
}
func getTeamRoles(schemeGuest, schemeUser, schemeAdmin bool, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole string, roles []string) rolesInfo {
result := rolesInfo{
roles: []string{},
explicitRoles: []string{},
schemeGuest: schemeGuest,
schemeUser: schemeUser,
schemeAdmin: schemeAdmin,
}
// Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude
// them from ExplicitRoles field.
schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
for _, role := range strings.Fields(db.Roles) {
isImplicit := false
if role == model.TEAM_GUEST_ROLE_ID {
// We have an implicit role via the system scheme. Override the "schemeGuest" field to true.
schemeGuest = true
isImplicit = true
} else if role == model.TEAM_USER_ROLE_ID {
// We have an implicit role via the system scheme. Override the "schemeUser" field to true.
schemeUser = true
isImplicit = true
} else if role == model.TEAM_ADMIN_ROLE_ID {
// We have an implicit role via the system scheme.
schemeAdmin = true
isImplicit = true
for _, role := range roles {
switch role {
case model.TEAM_GUEST_ROLE_ID:
result.schemeGuest = true
case model.TEAM_USER_ROLE_ID:
result.schemeUser = true
case model.TEAM_ADMIN_ROLE_ID:
result.schemeAdmin = true
default:
result.explicitRoles = append(result.explicitRoles, role)
result.roles = append(result.roles, role)
}
if !isImplicit {
explicitRoles = append(explicitRoles, role)
}
roles = append(roles, role)
}
// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
// them to the Roles field for backwards compatibility reasons.
var schemeImpliedRoles []string
if db.SchemeGuest.Valid && db.SchemeGuest.Bool {
if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String)
if result.schemeGuest {
if defaultTeamGuestRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamGuestRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_GUEST_ROLE_ID)
}
}
if db.SchemeUser.Valid && db.SchemeUser.Bool {
if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
if result.schemeUser {
if defaultTeamUserRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamUserRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_USER_ROLE_ID)
}
}
if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
if result.schemeAdmin {
if defaultTeamAdminRole != "" {
schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamAdminRole)
} else {
schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_ADMIN_ROLE_ID)
}
}
for _, impliedRole := range schemeImpliedRoles {
alreadyThere := false
for _, role := range roles {
for _, role := range result.roles {
if role == impliedRole {
alreadyThere = true
}
}
if !alreadyThere {
roles = append(roles, impliedRole)
result.roles = append(result.roles, impliedRole)
}
}
return result
}
func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember {
// Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude
// them from ExplicitRoles field.
schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
defaultTeamGuestRole := ""
if db.TeamSchemeDefaultGuestRole.Valid {
defaultTeamGuestRole = db.TeamSchemeDefaultGuestRole.String
}
defaultTeamUserRole := ""
if db.TeamSchemeDefaultUserRole.Valid {
defaultTeamUserRole = db.TeamSchemeDefaultUserRole.String
}
defaultTeamAdminRole := ""
if db.TeamSchemeDefaultAdminRole.Valid {
defaultTeamAdminRole = db.TeamSchemeDefaultAdminRole.String
}
rolesResult := getTeamRoles(schemeGuest, schemeUser, schemeAdmin, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole, strings.Fields(db.Roles))
tm := &model.TeamMember{
TeamId: db.TeamId,
UserId: db.UserId,
Roles: strings.Join(roles, " "),
Roles: strings.Join(rolesResult.roles, " "),
DeleteAt: db.DeleteAt,
SchemeGuest: schemeGuest,
SchemeUser: schemeUser,
SchemeAdmin: schemeAdmin,
ExplicitRoles: strings.Join(explicitRoles, " "),
SchemeGuest: rolesResult.schemeGuest,
SchemeUser: rolesResult.schemeUser,
SchemeAdmin: rolesResult.schemeAdmin,
ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
}
return tm
}
@@ -562,99 +605,224 @@ func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder {
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id")
}
// SaveMember adds a team member using the team Id of the member
// if the member does not already exist in the database and if the number
// of existing team members are less than the maximum allowed users per team.
// It returns the team member added if the operation is successful.
func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) (*model.TeamMember, *model.AppError) {
defer s.InvalidateAllTeamIdsForUser(member.UserId)
if err := member.IsValid(); err != nil {
return nil, err
func (s SqlTeamStore) SaveMultipleMembers(members []*model.TeamMember, maxUsersPerTeam int) ([]*model.TeamMember, *model.AppError) {
newTeamMembers := map[string]int{}
users := map[string]bool{}
for _, member := range members {
newTeamMembers[member.TeamId] = 0
}
for _, member := range members {
newTeamMembers[member.TeamId]++
users[member.UserId] = true
if err := member.IsValid(); err != nil {
return nil, err
}
}
teams := []string{}
for team := range newTeamMembers {
teams = append(teams, team)
}
defaultTeamRolesByTeam := map[string]struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}{}
queryRoles := s.getQueryBuilder().
Select(
"Teams.Id as Id",
"TeamScheme.DefaultTeamGuestRole as Guest",
"TeamScheme.DefaultTeamUserRole as User",
"TeamScheme.DefaultTeamAdminRole as Admin",
).
From("Teams").
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
Where(sq.Eq{"Teams.Id": teams})
sqlRolesQuery, argsRoles, err := queryRoles.ToSql()
if err != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var defaultTeamsRoles []struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}
_, err = s.GetMaster().Select(&defaultTeamsRoles, sqlRolesQuery, argsRoles...)
if err != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
for _, defaultRoles := range defaultTeamsRoles {
defaultTeamRolesByTeam[defaultRoles.Id] = defaultRoles
}
dbMember := NewTeamMemberFromModel(member)
if maxUsersPerTeam >= 0 {
count, err := s.GetMaster().SelectInt(
`SELECT
COUNT(0)
FROM
TeamMembers
INNER JOIN
Users
ON
TeamMembers.UserId = Users.Id
WHERE
TeamId = :TeamId
AND TeamMembers.DeleteAt = 0
AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": member.TeamId})
queryCount := s.getQueryBuilder().
Select(
"COUNT(0) as Count, TeamMembers.TeamId as TeamId",
).
From("TeamMembers").
Join("Users ON TeamMembers.UserId = Users.Id").
Where(sq.Eq{"TeamMembers.TeamId": teams}).
Where(sq.Eq{"TeamMembers.DeleteAt": 0}).
Where(sq.Eq{"Users.DeleteAt": 0}).
GroupBy("TeamMembers.TeamId")
sqlCountQuery, argsCount, errCount := queryCount.ToSql()
if errCount != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, errCount.Error(), http.StatusInternalServerError)
}
var counters []struct {
Count int `db:"Count"`
TeamId string `db:"TeamId"`
}
_, err = s.GetMaster().Select(&counters, sqlCountQuery, argsCount...)
if err != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, "teamId="+member.TeamId+", "+err.Error(), http.StatusInternalServerError)
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
if count >= int64(maxUsersPerTeam) {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.max_accounts.app_error", nil, "teamId="+member.TeamId, http.StatusBadRequest)
for teamId, newMembers := range newTeamMembers {
existingMembers := 0
for _, counter := range counters {
if counter.TeamId == teamId {
existingMembers = counter.Count
}
}
if existingMembers+newMembers > maxUsersPerTeam {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.max_accounts.app_error", nil, "", http.StatusBadRequest)
}
}
}
if err := s.GetMaster().Insert(dbMember); err != nil {
if IsUniqueConstraintError(err, []string{"TeamId", "teammembers_pkey", "PRIMARY"}) {
return nil, model.NewAppError("SqlTeamStore.SaveMember", TEAM_MEMBER_EXISTS_ERROR, nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
}
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.save_member.save.app_error", nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
query := s.getQueryBuilder().Insert("TeamMembers").Columns(teamMemberSliceColumns()...)
for _, member := range members {
query = query.Values(teamMemberToSlice(member)...)
}
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": dbMember.TeamId}).
Where(sq.Eq{"TeamMembers.UserId": dbMember.UserId})
queryString, args, err := query.ToSql()
sql, args, err := query.ToSql()
if err != nil {
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var retrievedMember teamMemberWithSchemeRoles
if err := s.GetMaster().SelectOne(&retrievedMember, queryString, args...); err != nil {
if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
if _, err := s.GetMaster().Exec(sql, args...); err != nil {
if IsUniqueConstraintError(err, []string{"TeamId", "teammembers_pkey", "PRIMARY"}) {
return nil, model.NewAppError("SqlTeamStore.SaveMember", TEAM_MEMBER_EXISTS_ERROR, nil, err.Error(), http.StatusBadRequest)
}
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError)
return nil, model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return retrievedMember.ToModel(), nil
newMembers := []*model.TeamMember{}
for _, member := range members {
s.InvalidateAllTeamIdsForUser(member.UserId)
defaultTeamGuestRole := defaultTeamRolesByTeam[member.TeamId].Guest.String
defaultTeamUserRole := defaultTeamRolesByTeam[member.TeamId].User.String
defaultTeamAdminRole := defaultTeamRolesByTeam[member.TeamId].Admin.String
rolesResult := getTeamRoles(member.SchemeGuest, member.SchemeUser, member.SchemeAdmin, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole, strings.Fields(member.ExplicitRoles))
newMember := *member
newMember.SchemeGuest = rolesResult.schemeGuest
newMember.SchemeUser = rolesResult.schemeUser
newMember.SchemeAdmin = rolesResult.schemeAdmin
newMember.Roles = strings.Join(rolesResult.roles, " ")
newMember.ExplicitRoles = strings.Join(rolesResult.explicitRoles, " ")
newMembers = append(newMembers, &newMember)
}
return newMembers, nil
}
// UpdateMember updates the team member if the team member exists in the database.
// It returns the updated team member if the operation is successful.
func (s SqlTeamStore) UpdateMember(member *model.TeamMember) (*model.TeamMember, *model.AppError) {
member.PreUpdate()
if err := member.IsValid(); err != nil {
func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) (*model.TeamMember, *model.AppError) {
members, err := s.SaveMultipleMembers([]*model.TeamMember{member}, maxUsersPerTeam)
if err != nil {
return nil, err
}
return members[0], nil
}
if _, err := s.GetMaster().Update(NewTeamMemberFromModel(member)); err != nil {
return nil, model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
func (s SqlTeamStore) UpdateMultipleMembers(members []*model.TeamMember) ([]*model.TeamMember, *model.AppError) {
teams := []string{}
for _, member := range members {
member.PreUpdate()
query := s.getTeamMembersWithSchemeSelectQuery().
Where(sq.Eq{"TeamMembers.TeamId": member.TeamId}).
Where(sq.Eq{"TeamMembers.UserId": member.UserId})
queryString, args, err := query.ToSql()
if err != nil {
return nil, model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var retrievedMember teamMemberWithSchemeRoles
if err := s.GetMaster().SelectOne(&retrievedMember, queryString, args...); err != nil {
if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
if err := member.IsValid(); err != nil {
return nil, err
}
return nil, model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
if _, err := s.GetMaster().Update(NewTeamMemberFromModel(member)); err != nil {
return nil, model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
}
teams = append(teams, member.TeamId)
}
return retrievedMember.ToModel(), nil
query := s.getQueryBuilder().
Select(
"Teams.Id as Id",
"TeamScheme.DefaultTeamGuestRole as Guest",
"TeamScheme.DefaultTeamUserRole as User",
"TeamScheme.DefaultTeamAdminRole as Admin",
).
From("Teams").
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
Where(sq.Eq{"Teams.Id": teams})
sqlQuery, args, err := query.ToSql()
if err != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
var defaultTeamsRoles []struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}
_, err = s.GetMaster().Select(&defaultTeamsRoles, sqlQuery, args...)
if err != nil {
return nil, model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
defaultTeamRolesByTeam := map[string]struct {
Id string
Guest sql.NullString
User sql.NullString
Admin sql.NullString
}{}
for _, defaultRoles := range defaultTeamsRoles {
defaultTeamRolesByTeam[defaultRoles.Id] = defaultRoles
}
updatedMembers := []*model.TeamMember{}
for _, member := range members {
s.InvalidateAllTeamIdsForUser(member.UserId)
defaultTeamGuestRole := defaultTeamRolesByTeam[member.TeamId].Guest.String
defaultTeamUserRole := defaultTeamRolesByTeam[member.TeamId].User.String
defaultTeamAdminRole := defaultTeamRolesByTeam[member.TeamId].Admin.String
rolesResult := getTeamRoles(member.SchemeGuest, member.SchemeUser, member.SchemeAdmin, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole, strings.Fields(member.ExplicitRoles))
updatedMember := *member
updatedMember.SchemeGuest = rolesResult.schemeGuest
updatedMember.SchemeUser = rolesResult.schemeUser
updatedMember.SchemeAdmin = rolesResult.schemeAdmin
updatedMember.Roles = strings.Join(rolesResult.roles, " ")
updatedMember.ExplicitRoles = strings.Join(rolesResult.explicitRoles, " ")
updatedMembers = append(updatedMembers, &updatedMember)
}
return updatedMembers, nil
}
func (s SqlTeamStore) UpdateMember(member *model.TeamMember) (*model.TeamMember, *model.AppError) {
members, err := s.UpdateMultipleMembers([]*model.TeamMember{member})
if err != nil {
return nil, err
}
return members[0], nil
}
func (s SqlTeamStore) GetMember(teamId string, userId string) (*model.TeamMember, *model.AppError) {
@@ -851,14 +1019,27 @@ func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) ([]*model.
return channels, nil
}
func (s SqlTeamStore) RemoveMember(teamId string, userId string) *model.AppError {
_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
func (s SqlTeamStore) RemoveMembers(teamId string, userIds []string) *model.AppError {
query := s.getQueryBuilder().
Delete("TeamMembers").
Where(sq.Eq{"TeamId": teamId}).
Where(sq.Eq{"UserId": userIds})
sql, args, err := query.ToSql()
if err != nil {
return model.NewAppError("SqlTeamStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
return model.NewAppError("SqlTeamStore.RemoveMembers", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
}
_, err = s.GetMaster().Exec(sql, args...)
if err != nil {
return model.NewAppError("SqlTeamStore.RemoveMembers", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
}
return nil
}
func (s SqlTeamStore) RemoveMember(teamId string, userId string) *model.AppError {
return s.RemoveMembers(teamId, []string{userId})
}
func (s SqlTeamStore) RemoveAllMembersByTeam(teamId string) *model.AppError {
_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId})
if err != nil {

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

@@ -150,7 +150,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) {
m := db.ToModel()
assert.Equal(t, "team_user custom_role", m.Roles)
assert.Equal(t, "custom_role team_user", m.Roles)
assert.Equal(t, false, m.SchemeGuest)
assert.Equal(t, true, m.SchemeUser)
assert.Equal(t, false, m.SchemeAdmin)
@@ -170,7 +170,7 @@ func testTeamMemberWithSchemeRolesToModel(t *testing.T) {
m := db.ToModel()
assert.Equal(t, "team_user team_admin custom_role", m.Roles)
assert.Equal(t, "custom_role team_user team_admin", m.Roles)
assert.Equal(t, false, m.SchemeGuest)
assert.Equal(t, true, m.SchemeUser)
assert.Equal(t, true, m.SchemeAdmin)