github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/group.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "errors" 8 "net/http" 9 10 "github.com/mattermost/mattermost-server/v5/model" 11 "github.com/mattermost/mattermost-server/v5/store" 12 ) 13 14 func (a *App) GetGroup(id string) (*model.Group, *model.AppError) { 15 group, err := a.Srv().Store.Group().Get(id) 16 if err != nil { 17 var nfErr *store.ErrNotFound 18 switch { 19 case errors.As(err, &nfErr): 20 return nil, model.NewAppError("GetGroup", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 21 default: 22 return nil, model.NewAppError("GetGroup", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 23 } 24 } 25 26 return group, nil 27 } 28 29 func (a *App) GetGroupByName(name string, opts model.GroupSearchOpts) (*model.Group, *model.AppError) { 30 group, err := a.Srv().Store.Group().GetByName(name, opts) 31 if err != nil { 32 var nfErr *store.ErrNotFound 33 switch { 34 case errors.As(err, &nfErr): 35 return nil, model.NewAppError("GetGroupByName", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 36 default: 37 return nil, model.NewAppError("GetGroupByName", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 38 } 39 } 40 41 return group, nil 42 } 43 44 func (a *App) GetGroupByRemoteID(remoteID string, groupSource model.GroupSource) (*model.Group, *model.AppError) { 45 group, err := a.Srv().Store.Group().GetByRemoteID(remoteID, groupSource) 46 if err != nil { 47 var nfErr *store.ErrNotFound 48 switch { 49 case errors.As(err, &nfErr): 50 return nil, model.NewAppError("GetGroupByRemoteID", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 51 default: 52 return nil, model.NewAppError("GetGroupByRemoteID", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 53 } 54 } 55 56 return group, nil 57 } 58 59 func (a *App) GetGroupsBySource(groupSource model.GroupSource) ([]*model.Group, *model.AppError) { 60 groups, err := a.Srv().Store.Group().GetAllBySource(groupSource) 61 if err != nil { 62 return nil, model.NewAppError("GetGroupsBySource", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 63 } 64 65 return groups, nil 66 } 67 68 func (a *App) GetGroupsByUserId(userID string) ([]*model.Group, *model.AppError) { 69 groups, err := a.Srv().Store.Group().GetByUser(userID) 70 if err != nil { 71 return nil, model.NewAppError("GetGroupsByUserId", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 72 } 73 74 return groups, nil 75 } 76 77 func (a *App) CreateGroup(group *model.Group) (*model.Group, *model.AppError) { 78 group, err := a.Srv().Store.Group().Create(group) 79 if err != nil { 80 var invErr *store.ErrInvalidInput 81 var appErr *model.AppError 82 switch { 83 case errors.As(err, &appErr): 84 return nil, appErr 85 case errors.As(err, &invErr): 86 return nil, model.NewAppError("CreateGroup", "app.group.id.app_error", nil, invErr.Error(), http.StatusBadRequest) 87 default: 88 return nil, model.NewAppError("CreateGroup", "app.insert_error", nil, err.Error(), http.StatusInternalServerError) 89 } 90 } 91 92 return group, nil 93 } 94 95 func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) { 96 updatedGroup, err := a.Srv().Store.Group().Update(group) 97 98 if err == nil { 99 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP, "", "", "", nil) 100 messageWs.Add("group", updatedGroup.ToJson()) 101 a.Publish(messageWs) 102 } 103 104 if err != nil { 105 var nfErr *store.ErrNotFound 106 var appErr *model.AppError 107 switch { 108 case errors.As(err, &appErr): 109 return nil, appErr 110 case errors.As(err, &nfErr): 111 return nil, model.NewAppError("UpdateGroup", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 112 default: 113 return nil, model.NewAppError("UpdateGroup", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 114 } 115 } 116 117 return updatedGroup, nil 118 } 119 120 func (a *App) DeleteGroup(groupID string) (*model.Group, *model.AppError) { 121 deletedGroup, err := a.Srv().Store.Group().Delete(groupID) 122 123 if err == nil { 124 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP, "", "", "", nil) 125 messageWs.Add("group", deletedGroup.ToJson()) 126 a.Publish(messageWs) 127 } 128 129 if err != nil { 130 var nfErr *store.ErrNotFound 131 switch { 132 case errors.As(err, &nfErr): 133 return nil, model.NewAppError("DeleteGroup", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 134 default: 135 return nil, model.NewAppError("DeleteGroup", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 136 } 137 } 138 139 return deletedGroup, nil 140 } 141 142 func (a *App) GetGroupMemberCount(groupID string) (int64, *model.AppError) { 143 count, err := a.Srv().Store.Group().GetMemberCount(groupID) 144 if err != nil { 145 return 0, model.NewAppError("GetGroupMemberCount", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 146 } 147 148 return count, nil 149 } 150 151 func (a *App) GetGroupMemberUsers(groupID string) ([]*model.User, *model.AppError) { 152 users, err := a.Srv().Store.Group().GetMemberUsers(groupID) 153 if err != nil { 154 return nil, model.NewAppError("GetGroupMemberUsers", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 155 } 156 157 return users, nil 158 } 159 160 func (a *App) GetGroupMemberUsersPage(groupID string, page int, perPage int) ([]*model.User, int, *model.AppError) { 161 members, err := a.Srv().Store.Group().GetMemberUsersPage(groupID, page, perPage) 162 if err != nil { 163 return nil, 0, model.NewAppError("GetGroupMemberUsersPage", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 164 } 165 166 count, appErr := a.GetGroupMemberCount(groupID) 167 if appErr != nil { 168 return nil, 0, appErr 169 } 170 return members, int(count), nil 171 } 172 173 func (a *App) UpsertGroupMember(groupID string, userID string) (*model.GroupMember, *model.AppError) { 174 groupMember, err := a.Srv().Store.Group().UpsertMember(groupID, userID) 175 if err != nil { 176 var invErr *store.ErrInvalidInput 177 var appErr *model.AppError 178 switch { 179 case errors.As(err, &appErr): 180 return nil, appErr 181 case errors.As(err, &invErr): 182 return nil, model.NewAppError("UpsertGroupMember", "app.group.uniqueness_error", nil, invErr.Error(), http.StatusBadRequest) 183 default: 184 return nil, model.NewAppError("UpsertGroupMember", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 185 } 186 } 187 188 return groupMember, nil 189 } 190 191 func (a *App) DeleteGroupMember(groupID string, userID string) (*model.GroupMember, *model.AppError) { 192 groupMember, err := a.Srv().Store.Group().DeleteMember(groupID, userID) 193 if err != nil { 194 var nfErr *store.ErrNotFound 195 switch { 196 case errors.As(err, &nfErr): 197 return nil, model.NewAppError("DeleteGroupMember", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 198 default: 199 return nil, model.NewAppError("DeleteGroupMember", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 200 } 201 } 202 203 return groupMember, nil 204 } 205 206 func (a *App) UpsertGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError) { 207 gs, err := a.Srv().Store.Group().GetGroupSyncable(groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type) 208 var notFoundErr *store.ErrNotFound 209 if err != nil && !errors.As(err, ¬FoundErr) { 210 return nil, model.NewAppError("UpsertGroupSyncable", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 211 } 212 213 // reject the syncable creation if the group isn't already associated to the parent team 214 if groupSyncable.Type == model.GroupSyncableTypeChannel { 215 channel, nErr := a.Srv().Store.Channel().Get(groupSyncable.SyncableId, true) 216 if nErr != nil { 217 var nfErr *store.ErrNotFound 218 switch { 219 case errors.As(nErr, &nfErr): 220 return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound) 221 default: 222 return nil, model.NewAppError("UpsertGroupSyncable", "app.channel.get.find.app_error", nil, nErr.Error(), http.StatusInternalServerError) 223 } 224 } 225 226 var team *model.Team 227 team, nErr = a.Srv().Store.Team().Get(channel.TeamId) 228 if nErr != nil { 229 var nfErr *store.ErrNotFound 230 switch { 231 case errors.As(nErr, &nfErr): 232 return nil, model.NewAppError("UpsertGroupSyncable", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 233 default: 234 return nil, model.NewAppError("UpsertGroupSyncable", "app.team.get.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError) 235 } 236 } 237 if team.IsGroupConstrained() { 238 var teamGroups []*model.GroupWithSchemeAdmin 239 teamGroups, err = a.Srv().Store.Group().GetGroupsByTeam(channel.TeamId, model.GroupSearchOpts{}) 240 if err != nil { 241 return nil, model.NewAppError("UpsertGroupSyncable", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 242 } 243 var permittedGroup bool 244 for _, teamGroup := range teamGroups { 245 if teamGroup.Group.Id == groupSyncable.GroupId { 246 permittedGroup = true 247 break 248 } 249 } 250 if !permittedGroup { 251 return nil, model.NewAppError("UpsertGroupSyncable", "group_not_associated_to_synced_team", nil, "", http.StatusBadRequest) 252 } 253 } else { 254 _, appErr := a.UpsertGroupSyncable(model.NewGroupTeam(groupSyncable.GroupId, team.Id, groupSyncable.AutoAdd)) 255 if appErr != nil { 256 return nil, appErr 257 } 258 } 259 } 260 261 if gs == nil { 262 gs, err = a.Srv().Store.Group().CreateGroupSyncable(groupSyncable) 263 if err != nil { 264 var nfErr *store.ErrNotFound 265 var appErr *model.AppError 266 switch { 267 case errors.As(err, &appErr): 268 return nil, appErr 269 case errors.As(err, &nfErr): 270 return nil, model.NewAppError("UpsertGroupSyncable", "store.sql_channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound) 271 default: 272 return nil, model.NewAppError("UpsertGroupSyncable", "app.insert_error", nil, err.Error(), http.StatusInternalServerError) 273 } 274 } 275 } else { 276 gs, err = a.Srv().Store.Group().UpdateGroupSyncable(groupSyncable) 277 if err != nil { 278 var appErr *model.AppError 279 switch { 280 case errors.As(err, &appErr): 281 return nil, appErr 282 default: 283 return nil, model.NewAppError("UpsertGroupSyncable", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 284 } 285 } 286 } 287 288 var messageWs *model.WebSocketEvent 289 if gs.Type == model.GroupSyncableTypeTeam { 290 messageWs = model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP_ASSOCIATED_TO_TEAM, gs.SyncableId, "", "", nil) 291 } else { 292 messageWs = model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP_ASSOCIATED_TO_CHANNEL, "", gs.SyncableId, "", nil) 293 } 294 messageWs.Add("group_id", gs.GroupId) 295 a.Publish(messageWs) 296 297 return gs, nil 298 } 299 300 func (a *App) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) { 301 group, err := a.Srv().Store.Group().GetGroupSyncable(groupID, syncableID, syncableType) 302 if err != nil { 303 var nfErr *store.ErrNotFound 304 switch { 305 case errors.As(err, &nfErr): 306 return nil, model.NewAppError("GetGroupSyncable", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 307 default: 308 return nil, model.NewAppError("GetGroupSyncable", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 309 } 310 } 311 312 return group, nil 313 } 314 315 func (a *App) GetGroupSyncables(groupID string, syncableType model.GroupSyncableType) ([]*model.GroupSyncable, *model.AppError) { 316 groups, err := a.Srv().Store.Group().GetAllGroupSyncablesByGroupId(groupID, syncableType) 317 if err != nil { 318 return nil, model.NewAppError("GetGroupSyncables", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 319 } 320 321 return groups, nil 322 } 323 324 func (a *App) UpdateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError) { 325 if groupSyncable.DeleteAt == 0 { 326 // updating a *deleted* GroupSyncable, so no need to ensure the GroupTeam is present (as done in the upsert) 327 gs, err := a.Srv().Store.Group().UpdateGroupSyncable(groupSyncable) 328 if err != nil { 329 var appErr *model.AppError 330 switch { 331 case errors.As(err, &appErr): 332 return nil, appErr 333 default: 334 return nil, model.NewAppError("UpdateGroupSyncable", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 335 } 336 } 337 338 return gs, nil 339 } 340 341 // do an upsert to ensure that there's an associated GroupTeam 342 gs, err := a.UpsertGroupSyncable(groupSyncable) 343 if err != nil { 344 return nil, err 345 } 346 347 return gs, nil 348 } 349 350 func (a *App) DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) { 351 gs, err := a.Srv().Store.Group().DeleteGroupSyncable(groupID, syncableID, syncableType) 352 if err != nil { 353 var invErr *store.ErrInvalidInput 354 var nfErr *store.ErrNotFound 355 switch { 356 case errors.As(err, &nfErr): 357 return nil, model.NewAppError("DeleteGroupSyncable", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 358 case errors.As(err, &invErr): 359 return nil, model.NewAppError("DeleteGroupSyncable", "app.group.group_syncable_already_deleted", nil, invErr.Error(), http.StatusBadRequest) 360 default: 361 return nil, model.NewAppError("DeleteGroupSyncable", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 362 } 363 } 364 365 // if a GroupTeam is being deleted delete all associated GroupChannels 366 if gs.Type == model.GroupSyncableTypeTeam { 367 allGroupChannels, err := a.Srv().Store.Group().GetAllGroupSyncablesByGroupId(gs.GroupId, model.GroupSyncableTypeChannel) 368 if err != nil { 369 return nil, model.NewAppError("DeleteGroupSyncable", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 370 } 371 372 for _, groupChannel := range allGroupChannels { 373 _, err = a.Srv().Store.Group().DeleteGroupSyncable(groupChannel.GroupId, groupChannel.SyncableId, groupChannel.Type) 374 if err != nil { 375 var invErr *store.ErrInvalidInput 376 var nfErr *store.ErrNotFound 377 switch { 378 case errors.As(err, &nfErr): 379 return nil, model.NewAppError("DeleteGroupSyncable", "app.group.no_rows", nil, nfErr.Error(), http.StatusNotFound) 380 case errors.As(err, &invErr): 381 return nil, model.NewAppError("DeleteGroupSyncable", "app.group.group_syncable_already_deleted", nil, invErr.Error(), http.StatusBadRequest) 382 default: 383 return nil, model.NewAppError("DeleteGroupSyncable", "app.update_error", nil, err.Error(), http.StatusInternalServerError) 384 } 385 } 386 } 387 } 388 389 var messageWs *model.WebSocketEvent 390 if gs.Type == model.GroupSyncableTypeTeam { 391 messageWs = model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP_NOT_ASSOCIATED_TO_TEAM, gs.SyncableId, "", "", nil) 392 } else { 393 messageWs = model.NewWebSocketEvent(model.WEBSOCKET_EVENT_RECEIVED_GROUP_NOT_ASSOCIATED_TO_CHANNEL, "", gs.SyncableId, "", nil) 394 } 395 396 messageWs.Add("group_id", gs.GroupId) 397 a.Publish(messageWs) 398 399 return gs, nil 400 } 401 402 func (a *App) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) { 403 userTeams, err := a.Srv().Store.Group().TeamMembersToAdd(since, teamID) 404 if err != nil { 405 return nil, model.NewAppError("TeamMembersToAdd", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 406 } 407 408 return userTeams, nil 409 } 410 411 func (a *App) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) { 412 userChannels, err := a.Srv().Store.Group().ChannelMembersToAdd(since, channelID) 413 if err != nil { 414 return nil, model.NewAppError("ChannelMembersToAdd", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 415 } 416 417 return userChannels, nil 418 } 419 420 func (a *App) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) { 421 teamMembers, err := a.Srv().Store.Group().TeamMembersToRemove(teamID) 422 if err != nil { 423 return nil, model.NewAppError("TeamMembersToRemove", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 424 } 425 426 return teamMembers, nil 427 } 428 429 func (a *App) ChannelMembersToRemove(teamID *string) ([]*model.ChannelMember, *model.AppError) { 430 channelMembers, err := a.Srv().Store.Group().ChannelMembersToRemove(teamID) 431 if err != nil { 432 return nil, model.NewAppError("ChannelMembersToRemove", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 433 } 434 435 return channelMembers, nil 436 } 437 438 func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, int, *model.AppError) { 439 groups, err := a.Srv().Store.Group().GetGroupsByChannel(channelId, opts) 440 if err != nil { 441 return nil, 0, model.NewAppError("GetGroupsByChannel", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 442 } 443 444 count, err := a.Srv().Store.Group().CountGroupsByChannel(channelId, opts) 445 if err != nil { 446 return nil, 0, model.NewAppError("GetGroupsByChannel", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 447 } 448 449 return groups, int(count), nil 450 } 451 452 // GetGroupsByTeam returns the paged list and the total count of group associated to the given team. 453 func (a *App) GetGroupsByTeam(teamID string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, int, *model.AppError) { 454 groups, err := a.Srv().Store.Group().GetGroupsByTeam(teamID, opts) 455 if err != nil { 456 return nil, 0, model.NewAppError("GetGroupsByTeam", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 457 } 458 459 count, err := a.Srv().Store.Group().CountGroupsByTeam(teamID, opts) 460 if err != nil { 461 return nil, 0, model.NewAppError("GetGroupsByTeam", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 462 } 463 464 return groups, int(count), nil 465 } 466 467 func (a *App) GetGroupsAssociatedToChannelsByTeam(teamID string, opts model.GroupSearchOpts) (map[string][]*model.GroupWithSchemeAdmin, *model.AppError) { 468 groupsAssociatedByChannelId, err := a.Srv().Store.Group().GetGroupsAssociatedToChannelsByTeam(teamID, opts) 469 if err != nil { 470 return nil, model.NewAppError("GetGroupsAssociatedToChannelsByTeam", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 471 } 472 473 return groupsAssociatedByChannelId, nil 474 } 475 476 func (a *App) GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) { 477 groups, err := a.Srv().Store.Group().GetGroups(page, perPage, opts) 478 if err != nil { 479 return nil, model.NewAppError("GetGroups", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 480 } 481 482 return groups, nil 483 } 484 485 // TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given 486 // groups. 487 // 488 // The result can be used, for example, to determine the set of users who would be removed from a team if the team 489 // were group-constrained with the given groups. 490 func (a *App) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, int64, *model.AppError) { 491 users, err := a.Srv().Store.Group().TeamMembersMinusGroupMembers(teamID, groupIDs, page, perPage) 492 if err != nil { 493 return nil, 0, model.NewAppError("TeamMembersMinusGroupMembers", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 494 } 495 496 // parse all group ids of all users 497 allUsersGroupIDMap := map[string]bool{} 498 for _, user := range users { 499 for _, groupID := range user.GetGroupIDs() { 500 allUsersGroupIDMap[groupID] = true 501 } 502 } 503 504 // create a slice of distinct group ids 505 var allUsersGroupIDSlice []string 506 for key := range allUsersGroupIDMap { 507 allUsersGroupIDSlice = append(allUsersGroupIDSlice, key) 508 } 509 510 // retrieve groups from DB 511 groups, appErr := a.GetGroupsByIDs(allUsersGroupIDSlice) 512 if appErr != nil { 513 return nil, 0, appErr 514 } 515 516 // map groups by id 517 groupMap := map[string]*model.Group{} 518 for _, group := range groups { 519 groupMap[group.Id] = group 520 } 521 522 // populate each instance's groups field 523 for _, user := range users { 524 user.Groups = []*model.Group{} 525 for _, groupID := range user.GetGroupIDs() { 526 group, ok := groupMap[groupID] 527 if ok { 528 user.Groups = append(user.Groups, group) 529 } 530 } 531 } 532 533 totalCount, err := a.Srv().Store.Group().CountTeamMembersMinusGroupMembers(teamID, groupIDs) 534 if err != nil { 535 return nil, 0, model.NewAppError("TeamMembersMinusGroupMembers", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 536 } 537 return users, totalCount, nil 538 } 539 540 func (a *App) GetGroupsByIDs(groupIDs []string) ([]*model.Group, *model.AppError) { 541 groups, err := a.Srv().Store.Group().GetByIDs(groupIDs) 542 if err != nil { 543 return nil, model.NewAppError("GetGroupsByIDs", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 544 } 545 546 return groups, nil 547 } 548 549 // ChannelMembersMinusGroupMembers returns the set of users in the given channel minus the set of users in the given 550 // groups. 551 // 552 // The result can be used, for example, to determine the set of users who would be removed from a channel if the 553 // channel were group-constrained with the given groups. 554 func (a *App) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, int64, *model.AppError) { 555 users, err := a.Srv().Store.Group().ChannelMembersMinusGroupMembers(channelID, groupIDs, page, perPage) 556 if err != nil { 557 return nil, 0, model.NewAppError("ChannelMembersMinusGroupMembers", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 558 } 559 560 // parse all group ids of all users 561 allUsersGroupIDMap := map[string]bool{} 562 for _, user := range users { 563 for _, groupID := range user.GetGroupIDs() { 564 allUsersGroupIDMap[groupID] = true 565 } 566 } 567 568 // create a slice of distinct group ids 569 var allUsersGroupIDSlice []string 570 for key := range allUsersGroupIDMap { 571 allUsersGroupIDSlice = append(allUsersGroupIDSlice, key) 572 } 573 574 // retrieve groups from DB 575 groups, appErr := a.GetGroupsByIDs(allUsersGroupIDSlice) 576 if appErr != nil { 577 return nil, 0, appErr 578 } 579 580 // map groups by id 581 groupMap := map[string]*model.Group{} 582 for _, group := range groups { 583 groupMap[group.Id] = group 584 } 585 586 // populate each instance's groups field 587 for _, user := range users { 588 user.Groups = []*model.Group{} 589 for _, groupID := range user.GetGroupIDs() { 590 group, ok := groupMap[groupID] 591 if ok { 592 user.Groups = append(user.Groups, group) 593 } 594 } 595 } 596 597 totalCount, err := a.Srv().Store.Group().CountChannelMembersMinusGroupMembers(channelID, groupIDs) 598 if err != nil { 599 return nil, 0, model.NewAppError("ChannelMembersMinusGroupMembers", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 600 } 601 return users, totalCount, nil 602 } 603 604 // UserIsInAdminRoleGroup returns true at least one of the user's groups are configured to set the members as 605 // admins in the given syncable. 606 func (a *App) UserIsInAdminRoleGroup(userID, syncableID string, syncableType model.GroupSyncableType) (bool, *model.AppError) { 607 groupIDs, err := a.Srv().Store.Group().AdminRoleGroupsForSyncableMember(userID, syncableID, syncableType) 608 if err != nil { 609 return false, model.NewAppError("UserIsInAdminRoleGroup", "app.select_error", nil, err.Error(), http.StatusInternalServerError) 610 } 611 612 if len(groupIDs) == 0 { 613 return false, nil 614 } 615 616 return true, nil 617 }