github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/store/sqlstore/group_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package sqlstore 5 6 import ( 7 "database/sql" 8 "fmt" 9 "strings" 10 11 sq "github.com/Masterminds/squirrel" 12 "github.com/pkg/errors" 13 14 "github.com/mattermost/mattermost-server/v5/model" 15 "github.com/mattermost/mattermost-server/v5/store" 16 ) 17 18 type selectType int 19 20 const ( 21 selectGroups selectType = iota 22 selectCountGroups 23 ) 24 25 type groupTeam struct { 26 model.GroupSyncable 27 TeamId string `db:"TeamId"` 28 } 29 30 type groupChannel struct { 31 model.GroupSyncable 32 ChannelId string `db:"ChannelId"` 33 } 34 35 type groupTeamJoin struct { 36 groupTeam 37 TeamDisplayName string `db:"TeamDisplayName"` 38 TeamType string `db:"TeamType"` 39 } 40 41 type groupChannelJoin struct { 42 groupChannel 43 ChannelDisplayName string `db:"ChannelDisplayName"` 44 TeamDisplayName string `db:"TeamDisplayName"` 45 TeamType string `db:"TeamType"` 46 ChannelType string `db:"ChannelType"` 47 TeamID string `db:"TeamId"` 48 } 49 50 type SqlGroupStore struct { 51 *SqlStore 52 } 53 54 func newSqlGroupStore(sqlStore *SqlStore) store.GroupStore { 55 s := &SqlGroupStore{SqlStore: sqlStore} 56 for _, db := range sqlStore.GetAllConns() { 57 groups := db.AddTableWithName(model.Group{}, "UserGroups").SetKeys(false, "Id") 58 groups.ColMap("Id").SetMaxSize(26) 59 groups.ColMap("Name").SetMaxSize(model.GroupNameMaxLength).SetUnique(true) 60 groups.ColMap("DisplayName").SetMaxSize(model.GroupDisplayNameMaxLength) 61 groups.ColMap("Description").SetMaxSize(model.GroupDescriptionMaxLength) 62 groups.ColMap("Source").SetMaxSize(model.GroupSourceMaxLength) 63 groups.ColMap("RemoteId").SetMaxSize(model.GroupRemoteIDMaxLength) 64 groups.SetUniqueTogether("Source", "RemoteId") 65 66 groupMembers := db.AddTableWithName(model.GroupMember{}, "GroupMembers").SetKeys(false, "GroupId", "UserId") 67 groupMembers.ColMap("GroupId").SetMaxSize(26) 68 groupMembers.ColMap("UserId").SetMaxSize(26) 69 70 groupTeams := db.AddTableWithName(groupTeam{}, "GroupTeams").SetKeys(false, "GroupId", "TeamId") 71 groupTeams.ColMap("GroupId").SetMaxSize(26) 72 groupTeams.ColMap("TeamId").SetMaxSize(26) 73 74 groupChannels := db.AddTableWithName(groupChannel{}, "GroupChannels").SetKeys(false, "GroupId", "ChannelId") 75 groupChannels.ColMap("GroupId").SetMaxSize(26) 76 groupChannels.ColMap("ChannelId").SetMaxSize(26) 77 } 78 return s 79 } 80 81 func (s *SqlGroupStore) createIndexesIfNotExists() { 82 s.CreateIndexIfNotExists("idx_groupmembers_create_at", "GroupMembers", "CreateAt") 83 s.CreateIndexIfNotExists("idx_usergroups_remote_id", "UserGroups", "RemoteId") 84 s.CreateIndexIfNotExists("idx_usergroups_delete_at", "UserGroups", "DeleteAt") 85 s.CreateIndexIfNotExists("idx_groupteams_teamid", "GroupTeams", "TeamId") 86 s.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId") 87 s.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(1)", "boolean") 88 s.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(1)", "boolean") 89 s.CreateIndexIfNotExists("idx_groupteams_schemeadmin", "GroupTeams", "SchemeAdmin") 90 s.CreateIndexIfNotExists("idx_groupchannels_schemeadmin", "GroupChannels", "SchemeAdmin") 91 } 92 93 func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, error) { 94 if group.Id != "" { 95 return nil, store.NewErrInvalidInput("Group", "id", group.Id) 96 } 97 98 if err := group.IsValidForCreate(); err != nil { 99 return nil, err 100 } 101 102 group.Id = model.NewId() 103 group.CreateAt = model.GetMillis() 104 group.UpdateAt = group.CreateAt 105 106 if err := s.GetMaster().Insert(group); err != nil { 107 if IsUniqueConstraintError(err, []string{"Name", "groups_name_key"}) { 108 return nil, errors.Wrapf(err, "Group with name %s already exists", *group.Name) 109 } 110 return nil, errors.Wrap(err, "failed to save Group") 111 } 112 113 return group, nil 114 } 115 116 func (s *SqlGroupStore) Get(groupId string) (*model.Group, error) { 117 var group *model.Group 118 if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE Id = :Id", map[string]interface{}{"Id": groupId}); err != nil { 119 if err == sql.ErrNoRows { 120 return nil, store.NewErrNotFound("Group", groupId) 121 } 122 return nil, errors.Wrapf(err, "failed to get Group with id=%s", groupId) 123 } 124 125 return group, nil 126 } 127 128 func (s *SqlGroupStore) GetByName(name string, opts model.GroupSearchOpts) (*model.Group, error) { 129 var group *model.Group 130 query := s.getQueryBuilder().Select("*").From("UserGroups").Where(sq.Eq{"Name": name}) 131 if opts.FilterAllowReference { 132 query = query.Where("AllowReference = true") 133 } 134 135 queryString, args, err := query.ToSql() 136 137 if err != nil { 138 return nil, errors.Wrap(err, "get_by_name_tosql") 139 } 140 if err := s.GetReplica().SelectOne(&group, queryString, args...); err != nil { 141 if err == sql.ErrNoRows { 142 return nil, store.NewErrNotFound("Group", fmt.Sprintf("name=%s", name)) 143 } 144 return nil, errors.Wrapf(err, "failed to get Group with name=%s", name) 145 } 146 147 return group, nil 148 } 149 150 func (s *SqlGroupStore) GetByIDs(groupIDs []string) ([]*model.Group, error) { 151 var groups []*model.Group 152 query := s.getQueryBuilder().Select("*").From("UserGroups").Where(sq.Eq{"Id": groupIDs}) 153 queryString, args, err := query.ToSql() 154 if err != nil { 155 return nil, errors.Wrap(err, "get_by_ids_tosql") 156 } 157 if _, err := s.GetReplica().Select(&groups, queryString, args...); err != nil { 158 return nil, errors.Wrap(err, "failed to find Groups by ids") 159 } 160 return groups, nil 161 } 162 163 func (s *SqlGroupStore) GetByRemoteID(remoteID string, groupSource model.GroupSource) (*model.Group, error) { 164 var group *model.Group 165 if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE RemoteId = :RemoteId AND Source = :Source", map[string]interface{}{"RemoteId": remoteID, "Source": groupSource}); err != nil { 166 if err == sql.ErrNoRows { 167 return nil, store.NewErrNotFound("Group", fmt.Sprintf("remoteId=%s", remoteID)) 168 } 169 return nil, errors.Wrapf(err, "failed to get Group with remoteId=%s", remoteID) 170 } 171 172 return group, nil 173 } 174 175 func (s *SqlGroupStore) GetAllBySource(groupSource model.GroupSource) ([]*model.Group, error) { 176 var groups []*model.Group 177 178 if _, err := s.GetReplica().Select(&groups, "SELECT * from UserGroups WHERE DeleteAt = 0 AND Source = :Source", map[string]interface{}{"Source": groupSource}); err != nil { 179 return nil, errors.Wrapf(err, "failed to find Groups by groupSource=%v", groupSource) 180 } 181 182 return groups, nil 183 } 184 185 func (s *SqlGroupStore) GetByUser(userId string) ([]*model.Group, error) { 186 var groups []*model.Group 187 188 query := ` 189 SELECT 190 UserGroups.* 191 FROM 192 GroupMembers 193 JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId 194 WHERE 195 GroupMembers.DeleteAt = 0 196 AND UserId = :UserId` 197 198 if _, err := s.GetReplica().Select(&groups, query, map[string]interface{}{"UserId": userId}); err != nil { 199 return nil, errors.Wrapf(err, "failed to find Groups with userId=%s", userId) 200 } 201 202 return groups, nil 203 } 204 205 func (s *SqlGroupStore) Update(group *model.Group) (*model.Group, error) { 206 var retrievedGroup *model.Group 207 if err := s.GetReplica().SelectOne(&retrievedGroup, "SELECT * FROM UserGroups WHERE Id = :Id", map[string]interface{}{"Id": group.Id}); err != nil { 208 if err == sql.ErrNoRows { 209 return nil, store.NewErrNotFound("Group", group.Id) 210 } 211 return nil, errors.Wrapf(err, "failed to get Group with id=%s", group.Id) 212 } 213 214 // If updating DeleteAt it can only be to 0 215 if group.DeleteAt != retrievedGroup.DeleteAt && group.DeleteAt != 0 { 216 return nil, errors.New("DeleteAt should be 0 when updating") 217 } 218 219 // Reset these properties, don't update them based on input 220 group.CreateAt = retrievedGroup.CreateAt 221 group.UpdateAt = model.GetMillis() 222 223 if err := group.IsValidForUpdate(); err != nil { 224 return nil, err 225 } 226 227 rowsChanged, err := s.GetMaster().Update(group) 228 if err != nil { 229 if IsUniqueConstraintError(err, []string{"Name", "groups_name_key"}) { 230 return nil, errors.Wrapf(err, "Group with name %s already exists", *group.Name) 231 } 232 return nil, errors.Wrap(err, "failed to update Group") 233 } 234 if rowsChanged > 1 { 235 return nil, errors.Wrapf(err, "multiple Groups were update: %d", rowsChanged) 236 } 237 238 return group, nil 239 } 240 241 func (s *SqlGroupStore) Delete(groupID string) (*model.Group, error) { 242 var group *model.Group 243 if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": groupID}); err != nil { 244 if err == sql.ErrNoRows { 245 return nil, store.NewErrNotFound("Group", groupID) 246 } 247 return nil, errors.Wrapf(err, "failed to get Group with id=%s", groupID) 248 } 249 250 time := model.GetMillis() 251 group.DeleteAt = time 252 group.UpdateAt = time 253 254 if _, err := s.GetMaster().Update(group); err != nil { 255 return nil, errors.Wrapf(err, "failed to update Group with id=%s", groupID) 256 } 257 258 return group, nil 259 } 260 261 func (s *SqlGroupStore) GetMemberUsers(groupID string) ([]*model.User, error) { 262 var groupMembers []*model.User 263 264 query := ` 265 SELECT 266 Users.* 267 FROM 268 GroupMembers 269 JOIN Users ON Users.Id = GroupMembers.UserId 270 WHERE 271 GroupMembers.DeleteAt = 0 272 AND Users.DeleteAt = 0 273 AND GroupId = :GroupId` 274 275 if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID}); err != nil { 276 return nil, errors.Wrapf(err, "failed to find member Users for Group with id=%s", groupID) 277 } 278 279 return groupMembers, nil 280 } 281 282 func (s *SqlGroupStore) GetMemberUsersPage(groupID string, page int, perPage int) ([]*model.User, error) { 283 var groupMembers []*model.User 284 285 query := ` 286 SELECT 287 Users.* 288 FROM 289 GroupMembers 290 JOIN Users ON Users.Id = GroupMembers.UserId 291 WHERE 292 GroupMembers.DeleteAt = 0 293 AND Users.DeleteAt = 0 294 AND GroupId = :GroupId 295 ORDER BY 296 GroupMembers.CreateAt DESC 297 LIMIT 298 :Limit 299 OFFSET 300 :Offset` 301 302 if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "Limit": perPage, "Offset": page * perPage}); err != nil { 303 return nil, errors.Wrapf(err, "failed to find member Users for Group with id=%s", groupID) 304 } 305 306 return groupMembers, nil 307 } 308 309 func (s *SqlGroupStore) GetMemberCount(groupID string) (int64, error) { 310 query := ` 311 SELECT 312 count(*) 313 FROM 314 GroupMembers 315 JOIN Users ON Users.Id = GroupMembers.UserId 316 WHERE 317 GroupMembers.GroupId = :GroupId 318 AND Users.DeleteAt = 0` 319 320 count, err := s.GetReplica().SelectInt(query, map[string]interface{}{"GroupId": groupID}) 321 if err != nil { 322 return int64(0), errors.Wrapf(err, "failed to count member Users for Group with id=%s", groupID) 323 } 324 325 return count, nil 326 } 327 328 func (s *SqlGroupStore) GetMemberUsersInTeam(groupID string, teamID string) ([]*model.User, error) { 329 var groupMembers []*model.User 330 331 query := ` 332 SELECT 333 Users.* 334 FROM 335 GroupMembers 336 JOIN Users ON Users.Id = GroupMembers.UserId 337 WHERE 338 GroupId = :GroupId 339 AND GroupMembers.UserId IN ( 340 SELECT TeamMembers.UserId 341 FROM TeamMembers 342 JOIN Teams ON Teams.Id = :TeamId 343 WHERE TeamMembers.TeamId = Teams.Id 344 AND TeamMembers.DeleteAt = 0 345 ) 346 AND GroupMembers.DeleteAt = 0 347 AND Users.DeleteAt = 0 348 ` 349 350 if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "TeamId": teamID}); err != nil { 351 return nil, errors.Wrapf(err, "failed to member Users for groupId=%s and teamId=%s", groupID, teamID) 352 } 353 354 return groupMembers, nil 355 } 356 357 func (s *SqlGroupStore) GetMemberUsersNotInChannel(groupID string, channelID string) ([]*model.User, error) { 358 var groupMembers []*model.User 359 360 query := ` 361 SELECT 362 Users.* 363 FROM 364 GroupMembers 365 JOIN Users ON Users.Id = GroupMembers.UserId 366 WHERE 367 GroupId = :GroupId 368 AND GroupMembers.UserId NOT IN ( 369 SELECT ChannelMembers.UserId 370 FROM ChannelMembers 371 WHERE ChannelMembers.ChannelId = :ChannelId 372 ) 373 AND GroupMembers.UserId IN ( 374 SELECT TeamMembers.UserId 375 FROM TeamMembers 376 JOIN Channels ON Channels.Id = :ChannelId 377 JOIN Teams ON Teams.Id = Channels.TeamId 378 WHERE TeamMembers.TeamId = Teams.Id 379 AND TeamMembers.DeleteAt = 0 380 ) 381 AND GroupMembers.DeleteAt = 0 382 AND Users.DeleteAt = 0 383 ` 384 385 if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "ChannelId": channelID}); err != nil { 386 return nil, errors.Wrapf(err, "failed to member Users for groupId=%s and channelId!=%s", groupID, channelID) 387 } 388 389 return groupMembers, nil 390 } 391 392 func (s *SqlGroupStore) UpsertMember(groupID string, userID string) (*model.GroupMember, error) { 393 member := &model.GroupMember{ 394 GroupId: groupID, 395 UserId: userID, 396 CreateAt: model.GetMillis(), 397 } 398 399 if err := member.IsValid(); err != nil { 400 return nil, err 401 } 402 403 var retrievedGroup *model.Group 404 if err := s.GetReplica().SelectOne(&retrievedGroup, "SELECT * FROM UserGroups WHERE Id = :Id", map[string]interface{}{"Id": groupID}); err != nil { 405 return nil, errors.Wrapf(err, "failed to get UserGroup with groupId=%s and userId=%s", groupID, userID) 406 } 407 408 var retrievedMember *model.GroupMember 409 if err := s.GetReplica().SelectOne(&retrievedMember, "SELECT * FROM GroupMembers WHERE GroupId = :GroupId AND UserId = :UserId", map[string]interface{}{"GroupId": member.GroupId, "UserId": member.UserId}); err != nil { 410 if err != sql.ErrNoRows { 411 return nil, errors.Wrapf(err, "failed to get GroupMember with groupId=%s and userId=%s", groupID, userID) 412 } 413 } 414 415 if retrievedMember == nil { 416 if err := s.GetMaster().Insert(member); err != nil { 417 if IsUniqueConstraintError(err, []string{"GroupId", "UserId", "groupmembers_pkey", "PRIMARY"}) { 418 return nil, store.NewErrInvalidInput("Member", "<groupId, userId>", fmt.Sprintf("<%s, %s>", groupID, userID)) 419 } 420 return nil, errors.Wrap(err, "failed to save Member") 421 } 422 } else { 423 member.DeleteAt = 0 424 var rowsChanged int64 425 var err error 426 if rowsChanged, err = s.GetMaster().Update(member); err != nil { 427 return nil, errors.Wrapf(err, "failed to update GroupMember with groupId=%s and userId=%s", groupID, userID) 428 } 429 if rowsChanged > 1 { 430 return nil, errors.Wrapf(err, "multiple GroupMembers were updated: %d", rowsChanged) 431 } 432 } 433 434 return member, nil 435 } 436 437 func (s *SqlGroupStore) DeleteMember(groupID string, userID string) (*model.GroupMember, error) { 438 var retrievedMember *model.GroupMember 439 if err := s.GetReplica().SelectOne(&retrievedMember, "SELECT * FROM GroupMembers WHERE GroupId = :GroupId AND UserId = :UserId AND DeleteAt = 0", map[string]interface{}{"GroupId": groupID, "UserId": userID}); err != nil { 440 if err == sql.ErrNoRows { 441 return nil, store.NewErrNotFound("GroupMember", fmt.Sprintf("groupId=%s, userId=%s", groupID, userID)) 442 } 443 return nil, errors.Wrapf(err, "failed to get GroupMember with groupId=%s and userId=%s", groupID, userID) 444 } 445 446 retrievedMember.DeleteAt = model.GetMillis() 447 448 if _, err := s.GetMaster().Update(retrievedMember); err != nil { 449 return nil, errors.Wrapf(err, "failed to update GroupMember with groupId=%s and userId=%s", groupID, userID) 450 } 451 452 return retrievedMember, nil 453 } 454 455 func (s *SqlGroupStore) PermanentDeleteMembersByUser(userId string) error { 456 if _, err := s.GetMaster().Exec("DELETE FROM GroupMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 457 return errors.Wrapf(err, "failed to permanent delete GroupMember with userId=%s", userId) 458 } 459 return nil 460 } 461 462 func (s *SqlGroupStore) CreateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, error) { 463 if err := groupSyncable.IsValid(); err != nil { 464 return nil, err 465 } 466 467 // Reset values that shouldn't be updatable by parameter 468 groupSyncable.DeleteAt = 0 469 groupSyncable.CreateAt = model.GetMillis() 470 groupSyncable.UpdateAt = groupSyncable.CreateAt 471 472 var insertErr error 473 474 switch groupSyncable.Type { 475 case model.GroupSyncableTypeTeam: 476 if _, err := s.Team().Get(groupSyncable.SyncableId); err != nil { 477 return nil, err 478 } 479 480 insertErr = s.GetMaster().Insert(groupSyncableToGroupTeam(groupSyncable)) 481 case model.GroupSyncableTypeChannel: 482 if _, err := s.Channel().Get(groupSyncable.SyncableId, false); err != nil { 483 return nil, err 484 } 485 486 insertErr = s.GetMaster().Insert(groupSyncableToGroupChannel(groupSyncable)) 487 default: 488 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 489 } 490 491 if insertErr != nil { 492 return nil, errors.Wrap(insertErr, "unable to insert GroupSyncable") 493 } 494 495 return groupSyncable, nil 496 } 497 498 func (s *SqlGroupStore) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 499 groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType) 500 if err != nil { 501 if err == sql.ErrNoRows { 502 return nil, store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType)) 503 } 504 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType) 505 } 506 507 return groupSyncable, nil 508 } 509 510 func (s *SqlGroupStore) getGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 511 var err error 512 var result interface{} 513 514 switch syncableType { 515 case model.GroupSyncableTypeTeam: 516 result, err = s.GetReplica().Get(groupTeam{}, groupID, syncableID) 517 case model.GroupSyncableTypeChannel: 518 result, err = s.GetReplica().Get(groupChannel{}, groupID, syncableID) 519 } 520 521 if err != nil { 522 return nil, err 523 } 524 525 if result == nil { 526 return nil, sql.ErrNoRows 527 } 528 529 groupSyncable := model.GroupSyncable{} 530 switch syncableType { 531 case model.GroupSyncableTypeTeam: 532 groupTeam := result.(*groupTeam) 533 groupSyncable.SyncableId = groupTeam.TeamId 534 groupSyncable.GroupId = groupTeam.GroupId 535 groupSyncable.AutoAdd = groupTeam.AutoAdd 536 groupSyncable.CreateAt = groupTeam.CreateAt 537 groupSyncable.DeleteAt = groupTeam.DeleteAt 538 groupSyncable.UpdateAt = groupTeam.UpdateAt 539 groupSyncable.Type = syncableType 540 case model.GroupSyncableTypeChannel: 541 groupChannel := result.(*groupChannel) 542 groupSyncable.SyncableId = groupChannel.ChannelId 543 groupSyncable.GroupId = groupChannel.GroupId 544 groupSyncable.AutoAdd = groupChannel.AutoAdd 545 groupSyncable.CreateAt = groupChannel.CreateAt 546 groupSyncable.DeleteAt = groupChannel.DeleteAt 547 groupSyncable.UpdateAt = groupChannel.UpdateAt 548 groupSyncable.Type = syncableType 549 default: 550 return nil, fmt.Errorf("unable to convert syncableType: %s", syncableType.String()) 551 } 552 553 return &groupSyncable, nil 554 } 555 556 func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableType model.GroupSyncableType) ([]*model.GroupSyncable, error) { 557 args := map[string]interface{}{"GroupId": groupID} 558 559 groupSyncables := []*model.GroupSyncable{} 560 561 switch syncableType { 562 case model.GroupSyncableTypeTeam: 563 sqlQuery := ` 564 SELECT 565 GroupTeams.*, 566 Teams.DisplayName AS TeamDisplayName, 567 Teams.Type AS TeamType 568 FROM 569 GroupTeams 570 JOIN Teams ON Teams.Id = GroupTeams.TeamId 571 WHERE 572 GroupId = :GroupId AND GroupTeams.DeleteAt = 0` 573 574 results := []*groupTeamJoin{} 575 _, err := s.GetReplica().Select(&results, sqlQuery, args) 576 if err != nil { 577 return nil, errors.Wrapf(err, "failed to find GroupTeams with groupId=%s", groupID) 578 } 579 for _, result := range results { 580 groupSyncable := &model.GroupSyncable{ 581 SyncableId: result.TeamId, 582 GroupId: result.GroupId, 583 AutoAdd: result.AutoAdd, 584 CreateAt: result.CreateAt, 585 DeleteAt: result.DeleteAt, 586 UpdateAt: result.UpdateAt, 587 Type: syncableType, 588 TeamDisplayName: result.TeamDisplayName, 589 TeamType: result.TeamType, 590 SchemeAdmin: result.SchemeAdmin, 591 } 592 groupSyncables = append(groupSyncables, groupSyncable) 593 } 594 case model.GroupSyncableTypeChannel: 595 sqlQuery := ` 596 SELECT 597 GroupChannels.*, 598 Channels.DisplayName AS ChannelDisplayName, 599 Teams.DisplayName AS TeamDisplayName, 600 Channels.Type As ChannelType, 601 Teams.Type As TeamType, 602 Teams.Id AS TeamId 603 FROM 604 GroupChannels 605 JOIN Channels ON Channels.Id = GroupChannels.ChannelId 606 JOIN Teams ON Teams.Id = Channels.TeamId 607 WHERE 608 GroupId = :GroupId AND GroupChannels.DeleteAt = 0` 609 610 results := []*groupChannelJoin{} 611 _, err := s.GetReplica().Select(&results, sqlQuery, args) 612 if err != nil { 613 return nil, errors.Wrapf(err, "failed to find GroupChannels with groupId=%s", groupID) 614 } 615 for _, result := range results { 616 groupSyncable := &model.GroupSyncable{ 617 SyncableId: result.ChannelId, 618 GroupId: result.GroupId, 619 AutoAdd: result.AutoAdd, 620 CreateAt: result.CreateAt, 621 DeleteAt: result.DeleteAt, 622 UpdateAt: result.UpdateAt, 623 Type: syncableType, 624 ChannelDisplayName: result.ChannelDisplayName, 625 ChannelType: result.ChannelType, 626 TeamDisplayName: result.TeamDisplayName, 627 TeamType: result.TeamType, 628 TeamID: result.TeamID, 629 SchemeAdmin: result.SchemeAdmin, 630 } 631 groupSyncables = append(groupSyncables, groupSyncable) 632 } 633 } 634 635 return groupSyncables, nil 636 } 637 638 func (s *SqlGroupStore) UpdateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, error) { 639 retrievedGroupSyncable, err := s.getGroupSyncable(groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type) 640 if err != nil { 641 if err == sql.ErrNoRows { 642 return nil, errors.Wrap(store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type)), "GroupSyncable not found") 643 } 644 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type) 645 } 646 647 if err := groupSyncable.IsValid(); err != nil { 648 return nil, err 649 } 650 651 // If updating DeleteAt it can only be to 0 652 if groupSyncable.DeleteAt != retrievedGroupSyncable.DeleteAt && groupSyncable.DeleteAt != 0 { 653 return nil, errors.New("DeleteAt should be 0 when updating") 654 } 655 656 // Reset these properties, don't update them based on input 657 groupSyncable.CreateAt = retrievedGroupSyncable.CreateAt 658 groupSyncable.UpdateAt = model.GetMillis() 659 660 switch groupSyncable.Type { 661 case model.GroupSyncableTypeTeam: 662 _, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable)) 663 case model.GroupSyncableTypeChannel: 664 _, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable)) 665 default: 666 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 667 } 668 669 if err != nil { 670 return nil, errors.Wrap(err, "failed to update GroupSyncable") 671 } 672 673 return groupSyncable, nil 674 } 675 676 func (s *SqlGroupStore) DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 677 groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType) 678 if err != nil { 679 if err == sql.ErrNoRows { 680 return nil, store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType)) 681 } 682 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType) 683 } 684 685 if groupSyncable.DeleteAt != 0 { 686 return nil, store.NewErrInvalidInput("GroupSyncable", "<groupId, syncableId, syncableType>", fmt.Sprintf("<%s, %s, %s>", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type)) 687 } 688 689 time := model.GetMillis() 690 groupSyncable.DeleteAt = time 691 groupSyncable.UpdateAt = time 692 693 switch groupSyncable.Type { 694 case model.GroupSyncableTypeTeam: 695 _, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable)) 696 case model.GroupSyncableTypeChannel: 697 _, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable)) 698 default: 699 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 700 } 701 702 if err != nil { 703 return nil, errors.Wrap(err, "failed to update GroupSyncable") 704 } 705 706 return groupSyncable, nil 707 } 708 709 func (s *SqlGroupStore) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, error) { 710 builder := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupTeams.TeamId"). 711 From("GroupMembers"). 712 Join("GroupTeams ON GroupTeams.GroupId = GroupMembers.GroupId"). 713 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 714 Join("Teams ON Teams.Id = GroupTeams.TeamId"). 715 JoinClause("LEFT OUTER JOIN TeamMembers ON TeamMembers.TeamId = GroupTeams.TeamId AND TeamMembers.UserId = GroupMembers.UserId"). 716 Where(sq.Eq{ 717 "TeamMembers.UserId": nil, 718 "UserGroups.DeleteAt": 0, 719 "GroupTeams.DeleteAt": 0, 720 "GroupTeams.AutoAdd": true, 721 "GroupMembers.DeleteAt": 0, 722 "Teams.DeleteAt": 0, 723 }). 724 Where("(GroupMembers.CreateAt >= ? OR GroupTeams.UpdateAt >= ?)", since, since) 725 726 if teamID != nil { 727 builder = builder.Where(sq.Eq{"Teams.Id": *teamID}) 728 } 729 730 query, params, err := builder.ToSql() 731 if err != nil { 732 return nil, errors.Wrap(err, "team_members_to_add_tosql") 733 } 734 735 var teamMembers []*model.UserTeamIDPair 736 737 _, err = s.GetReplica().Select(&teamMembers, query, params...) 738 if err != nil { 739 return nil, errors.Wrap(err, "failed to find UserTeamIDPairs") 740 } 741 742 return teamMembers, nil 743 } 744 745 func (s *SqlGroupStore) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, error) { 746 builder := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupChannels.ChannelId"). 747 From("GroupMembers"). 748 Join("GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId"). 749 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 750 Join("Channels ON Channels.Id = GroupChannels.ChannelId"). 751 JoinClause("LEFT OUTER JOIN ChannelMemberHistory ON ChannelMemberHistory.ChannelId = GroupChannels.ChannelId AND ChannelMemberHistory.UserId = GroupMembers.UserId"). 752 Where(sq.Eq{ 753 "ChannelMemberHistory.UserId": nil, 754 "ChannelMemberHistory.LeaveTime": nil, 755 "UserGroups.DeleteAt": 0, 756 "GroupChannels.DeleteAt": 0, 757 "GroupChannels.AutoAdd": true, 758 "GroupMembers.DeleteAt": 0, 759 "Channels.DeleteAt": 0, 760 }). 761 Where("(GroupMembers.CreateAt >= ? OR GroupChannels.UpdateAt >= ?)", since, since) 762 763 if channelID != nil { 764 builder = builder.Where(sq.Eq{"Channels.Id": *channelID}) 765 } 766 767 query, params, err := builder.ToSql() 768 if err != nil { 769 return nil, errors.Wrap(err, "channel_members_to_add_tosql") 770 } 771 772 var channelMembers []*model.UserChannelIDPair 773 774 _, err = s.GetReplica().Select(&channelMembers, query, params...) 775 if err != nil { 776 return nil, errors.Wrap(err, "failed to find UserChannelIDPairs") 777 } 778 779 return channelMembers, nil 780 } 781 782 func groupSyncableToGroupTeam(groupSyncable *model.GroupSyncable) *groupTeam { 783 return &groupTeam{ 784 GroupSyncable: *groupSyncable, 785 TeamId: groupSyncable.SyncableId, 786 } 787 } 788 789 func groupSyncableToGroupChannel(groupSyncable *model.GroupSyncable) *groupChannel { 790 return &groupChannel{ 791 GroupSyncable: *groupSyncable, 792 ChannelId: groupSyncable.SyncableId, 793 } 794 } 795 796 func (s *SqlGroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, error) { 797 whereStmt := ` 798 (TeamMembers.TeamId, 799 TeamMembers.UserId) 800 NOT IN ( 801 SELECT 802 Teams.Id AS TeamId, 803 GroupMembers.UserId 804 FROM 805 Teams 806 JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id 807 JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId 808 JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id 809 WHERE 810 Teams.GroupConstrained = TRUE 811 AND GroupTeams.DeleteAt = 0 812 AND UserGroups.DeleteAt = 0 813 AND Teams.DeleteAt = 0 814 AND GroupMembers.DeleteAt = 0 815 GROUP BY 816 Teams.Id, 817 GroupMembers.UserId)` 818 819 builder := s.getQueryBuilder().Select( 820 "TeamMembers.TeamId", 821 "TeamMembers.UserId", 822 "TeamMembers.Roles", 823 "TeamMembers.DeleteAt", 824 "TeamMembers.SchemeUser", 825 "TeamMembers.SchemeAdmin", 826 "(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) AS SchemeGuest", 827 ). 828 From("TeamMembers"). 829 Join("Teams ON Teams.Id = TeamMembers.TeamId"). 830 LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId"). 831 Where(sq.Eq{"TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0, "Teams.GroupConstrained": true, "Bots.UserId": nil}). 832 Where(whereStmt) 833 834 if teamID != nil { 835 builder = builder.Where(sq.Eq{"TeamMembers.TeamId": *teamID}) 836 } 837 838 query, params, err := builder.ToSql() 839 if err != nil { 840 return nil, errors.Wrap(err, "team_members_to_remove_tosql") 841 } 842 843 var teamMembers []*model.TeamMember 844 845 _, err = s.GetReplica().Select(&teamMembers, query, params...) 846 if err != nil { 847 return nil, errors.Wrap(err, "failed to find TeamMembers") 848 } 849 850 return teamMembers, nil 851 } 852 853 func (s *SqlGroupStore) CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, error) { 854 countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectCountGroups, channelId, opts) 855 856 countQueryString, args, err := countQuery.ToSql() 857 if err != nil { 858 return int64(0), errors.Wrap(err, "count_groups_by_channel_tosql") 859 } 860 861 count, err := s.GetReplica().SelectInt(countQueryString, args...) 862 if err != nil { 863 return int64(0), errors.Wrapf(err, "failed to count Groups by channel with channelId=%s", channelId) 864 } 865 866 return count, nil 867 } 868 869 func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, error) { 870 query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectGroups, channelId, opts) 871 872 if opts.PageOpts != nil { 873 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 874 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 875 } 876 877 queryString, args, err := query.ToSql() 878 if err != nil { 879 return nil, errors.Wrap(err, "get_groups_by_channel_tosql") 880 } 881 882 var groups []*model.GroupWithSchemeAdmin 883 884 _, err = s.GetReplica().Select(&groups, queryString, args...) 885 if err != nil { 886 return nil, errors.Wrapf(err, "failed to find Groups with channelId=%s", channelId) 887 } 888 889 return groups, nil 890 } 891 892 func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, error) { 893 whereStmt := ` 894 (ChannelMembers.ChannelId, 895 ChannelMembers.UserId) 896 NOT IN ( 897 SELECT 898 Channels.Id AS ChannelId, 899 GroupMembers.UserId 900 FROM 901 Channels 902 JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id 903 JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId 904 JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id 905 WHERE 906 Channels.GroupConstrained = TRUE 907 AND GroupChannels.DeleteAt = 0 908 AND UserGroups.DeleteAt = 0 909 AND Channels.DeleteAt = 0 910 AND GroupMembers.DeleteAt = 0 911 GROUP BY 912 Channels.Id, 913 GroupMembers.UserId)` 914 915 builder := s.getQueryBuilder().Select( 916 "ChannelMembers.ChannelId", 917 "ChannelMembers.UserId", 918 "ChannelMembers.LastViewedAt", 919 "ChannelMembers.MsgCount", 920 "ChannelMembers.MentionCount", 921 "ChannelMembers.NotifyProps", 922 "ChannelMembers.LastUpdateAt", 923 "ChannelMembers.LastUpdateAt", 924 "ChannelMembers.SchemeUser", 925 "ChannelMembers.SchemeAdmin", 926 "(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) AS SchemeGuest", 927 ). 928 From("ChannelMembers"). 929 Join("Channels ON Channels.Id = ChannelMembers.ChannelId"). 930 LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId"). 931 Where(sq.Eq{"Channels.DeleteAt": 0, "Channels.GroupConstrained": true, "Bots.UserId": nil}). 932 Where(whereStmt) 933 934 if channelID != nil { 935 builder = builder.Where(sq.Eq{"ChannelMembers.ChannelId": *channelID}) 936 } 937 938 query, params, err := builder.ToSql() 939 if err != nil { 940 return nil, errors.Wrap(err, "channel_members_to_remove_tosql") 941 } 942 943 var channelMembers []*model.ChannelMember 944 945 _, err = s.GetReplica().Select(&channelMembers, query, params...) 946 if err != nil { 947 return nil, errors.Wrap(err, "failed to find ChannelMembers") 948 } 949 950 return channelMembers, nil 951 } 952 953 func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t selectType, syncableID string, opts model.GroupSearchOpts) sq.SelectBuilder { 954 selectStrs := map[selectType]string{ 955 selectGroups: "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin", 956 selectCountGroups: "COUNT(*)", 957 } 958 959 var table string 960 var idCol string 961 if st == model.GroupSyncableTypeTeam { 962 table = "GroupTeams" 963 idCol = "TeamId" 964 } else { 965 table = "GroupChannels" 966 idCol = "ChannelId" 967 } 968 969 query := s.getQueryBuilder(). 970 Select(selectStrs[t]). 971 From(fmt.Sprintf("%s gs", table)). 972 LeftJoin("UserGroups ug ON gs.GroupId = ug.Id"). 973 Where(fmt.Sprintf("ug.DeleteAt = 0 AND gs.%s = ? AND gs.DeleteAt = 0", idCol), syncableID) 974 975 if opts.IncludeMemberCount && t == selectGroups { 976 query = s.getQueryBuilder(). 977 Select(fmt.Sprintf("ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, Group%ss.SchemeAdmin AS SyncableSchemeAdmin", st)). 978 From("UserGroups ug"). 979 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"). 980 LeftJoin(fmt.Sprintf("%[1]s ON %[1]s.GroupId = ug.Id", table)). 981 Where(fmt.Sprintf("ug.DeleteAt = 0 AND %[1]s.DeleteAt = 0 AND %[1]s.%[2]s = ?", table, idCol), syncableID). 982 OrderBy("ug.DisplayName") 983 } 984 985 if opts.FilterAllowReference && t == selectGroups { 986 query = query.Where("ug.AllowReference = true") 987 } 988 989 if opts.Q != "" { 990 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 991 operatorKeyword := "ILIKE" 992 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 993 operatorKeyword = "LIKE" 994 } 995 query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 996 } 997 998 return query 999 } 1000 1001 func (s *SqlGroupStore) getGroupsAssociatedToChannelsByTeam(teamID string, opts model.GroupSearchOpts) sq.SelectBuilder { 1002 query := s.getQueryBuilder(). 1003 Select("gc.ChannelId, ug.*, gc.SchemeAdmin AS SyncableSchemeAdmin"). 1004 From("UserGroups ug"). 1005 LeftJoin(` 1006 (SELECT 1007 GroupChannels.GroupId, GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.SchemeAdmin 1008 FROM 1009 GroupChannels 1010 LEFT JOIN 1011 Channels ON (Channels.Id = GroupChannels.ChannelId) 1012 WHERE 1013 GroupChannels.DeleteAt = 0 1014 AND Channels.DeleteAt = 0 1015 AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID). 1016 Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0"). 1017 OrderBy("ug.DisplayName") 1018 1019 if opts.IncludeMemberCount { 1020 query = s.getQueryBuilder(). 1021 Select("gc.ChannelId, ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, gc.SchemeAdmin AS SyncableSchemeAdmin"). 1022 From("UserGroups ug"). 1023 LeftJoin(` 1024 (SELECT 1025 GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.GroupId, GroupChannels.SchemeAdmin 1026 FROM 1027 GroupChannels 1028 LEFT JOIN 1029 Channels ON (Channels.Id = GroupChannels.ChannelId) 1030 WHERE 1031 GroupChannels.DeleteAt = 0 1032 AND Channels.DeleteAt = 0 1033 AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID). 1034 LeftJoin(`( 1035 SELECT 1036 GroupMembers.GroupId, COUNT(*) AS MemberCount 1037 FROM 1038 GroupMembers 1039 LEFT JOIN 1040 Users ON Users.Id = GroupMembers.UserId 1041 WHERE 1042 GroupMembers.DeleteAt = 0 1043 AND Users.DeleteAt = 0 1044 GROUP BY GroupId) AS Members 1045 ON Members.GroupId = ug.Id`). 1046 Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0"). 1047 OrderBy("ug.DisplayName") 1048 } 1049 1050 if opts.FilterAllowReference { 1051 query = query.Where("ug.AllowReference = true") 1052 } 1053 1054 if opts.Q != "" { 1055 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 1056 operatorKeyword := "ILIKE" 1057 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1058 operatorKeyword = "LIKE" 1059 } 1060 query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 1061 } 1062 1063 return query 1064 } 1065 1066 func (s *SqlGroupStore) CountGroupsByTeam(teamId string, opts model.GroupSearchOpts) (int64, error) { 1067 countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectCountGroups, teamId, opts) 1068 1069 countQueryString, args, err := countQuery.ToSql() 1070 if err != nil { 1071 return int64(0), errors.Wrap(err, "count_groups_by_team_tosql") 1072 } 1073 1074 count, err := s.GetReplica().SelectInt(countQueryString, args...) 1075 if err != nil { 1076 return int64(0), errors.Wrapf(err, "failed to count Groups with teamId=%s", teamId) 1077 } 1078 1079 return count, nil 1080 } 1081 1082 func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, error) { 1083 query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectGroups, teamId, opts) 1084 1085 if opts.PageOpts != nil { 1086 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 1087 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 1088 } 1089 1090 queryString, args, err := query.ToSql() 1091 if err != nil { 1092 return nil, errors.Wrap(err, "get_groups_by_team_tosql") 1093 } 1094 1095 var groups []*model.GroupWithSchemeAdmin 1096 1097 _, err = s.GetReplica().Select(&groups, queryString, args...) 1098 if err != nil { 1099 return nil, errors.Wrapf(err, "failed to find Groups with teamId=%s", teamId) 1100 } 1101 1102 return groups, nil 1103 } 1104 1105 func (s *SqlGroupStore) GetGroupsAssociatedToChannelsByTeam(teamId string, opts model.GroupSearchOpts) (map[string][]*model.GroupWithSchemeAdmin, error) { 1106 query := s.getGroupsAssociatedToChannelsByTeam(teamId, opts) 1107 1108 if opts.PageOpts != nil { 1109 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 1110 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 1111 } 1112 1113 queryString, args, err := query.ToSql() 1114 if err != nil { 1115 return nil, errors.Wrap(err, "get_groups_associated_to_channel_by_team_tosql") 1116 } 1117 1118 var tgroups []*model.GroupsAssociatedToChannelWithSchemeAdmin 1119 1120 _, err = s.GetReplica().Select(&tgroups, queryString, args...) 1121 if err != nil { 1122 return nil, errors.Wrapf(err, "failed to find Groups with teamId=%s", teamId) 1123 } 1124 1125 groups := map[string][]*model.GroupWithSchemeAdmin{} 1126 for _, tgroup := range tgroups { 1127 var group = model.GroupWithSchemeAdmin{} 1128 group.Group = tgroup.Group 1129 group.SchemeAdmin = tgroup.SchemeAdmin 1130 1131 if val, ok := groups[tgroup.ChannelId]; ok { 1132 groups[tgroup.ChannelId] = append(val, &group) 1133 } else { 1134 groups[tgroup.ChannelId] = []*model.GroupWithSchemeAdmin{&group} 1135 } 1136 } 1137 1138 return groups, nil 1139 } 1140 1141 func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, error) { 1142 var groups []*model.Group 1143 1144 groupsQuery := s.getQueryBuilder().Select("g.*") 1145 1146 if opts.IncludeMemberCount { 1147 groupsQuery = s.getQueryBuilder(). 1148 Select("g.*, coalesce(Members.MemberCount, 0) AS MemberCount"). 1149 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 = g.Id") 1150 } 1151 1152 groupsQuery = groupsQuery. 1153 From("UserGroups g"). 1154 OrderBy("g.DisplayName") 1155 1156 if opts.Since > 0 { 1157 groupsQuery = groupsQuery.Where(sq.Gt{ 1158 "g.UpdateAt": opts.Since, 1159 }) 1160 } else { 1161 groupsQuery = groupsQuery.Where("g.DeleteAt = 0") 1162 } 1163 1164 if perPage != 0 { 1165 groupsQuery = groupsQuery. 1166 Limit(uint64(perPage)). 1167 Offset(uint64(page * perPage)) 1168 } 1169 1170 if opts.FilterAllowReference { 1171 groupsQuery = groupsQuery.Where("g.AllowReference = true") 1172 } 1173 1174 if opts.Q != "" { 1175 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 1176 operatorKeyword := "ILIKE" 1177 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1178 operatorKeyword = "LIKE" 1179 } 1180 groupsQuery = groupsQuery.Where(fmt.Sprintf("(g.Name %[1]s ? OR g.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 1181 } 1182 1183 if len(opts.NotAssociatedToTeam) == 26 { 1184 groupsQuery = groupsQuery.Where(` 1185 g.Id NOT IN ( 1186 SELECT 1187 Id 1188 FROM 1189 UserGroups 1190 JOIN GroupTeams ON GroupTeams.GroupId = UserGroups.Id 1191 WHERE 1192 GroupTeams.DeleteAt = 0 1193 AND UserGroups.DeleteAt = 0 1194 AND GroupTeams.TeamId = ? 1195 ) 1196 `, opts.NotAssociatedToTeam) 1197 } 1198 1199 if len(opts.NotAssociatedToChannel) == 26 { 1200 groupsQuery = groupsQuery.Where(` 1201 g.Id NOT IN ( 1202 SELECT 1203 Id 1204 FROM 1205 UserGroups 1206 JOIN GroupChannels ON GroupChannels.GroupId = UserGroups.Id 1207 WHERE 1208 GroupChannels.DeleteAt = 0 1209 AND UserGroups.DeleteAt = 0 1210 AND GroupChannels.ChannelId = ? 1211 ) 1212 `, opts.NotAssociatedToChannel) 1213 } 1214 1215 if opts.FilterParentTeamPermitted && len(opts.NotAssociatedToChannel) == 26 { 1216 groupsQuery = groupsQuery.Where(` 1217 CASE 1218 WHEN ( 1219 SELECT 1220 Teams.GroupConstrained 1221 FROM 1222 Teams 1223 JOIN Channels ON Channels.TeamId = Teams.Id 1224 WHERE 1225 Channels.Id = ? 1226 ) THEN g.Id IN ( 1227 SELECT 1228 GroupId 1229 FROM 1230 GroupTeams 1231 WHERE 1232 GroupTeams.DeleteAt = 0 1233 AND GroupTeams.TeamId = ( 1234 SELECT 1235 TeamId 1236 FROM 1237 Channels 1238 WHERE 1239 Id = ? 1240 ) 1241 ) 1242 ELSE TRUE 1243 END 1244 `, opts.NotAssociatedToChannel, opts.NotAssociatedToChannel) 1245 } 1246 1247 queryString, args, err := groupsQuery.ToSql() 1248 if err != nil { 1249 return nil, errors.Wrap(err, "get_groups_tosql") 1250 } 1251 1252 if _, err = s.GetReplica().Select(&groups, queryString, args...); err != nil { 1253 return nil, errors.Wrap(err, "failed to find Groups") 1254 } 1255 1256 return groups, nil 1257 } 1258 1259 func (s *SqlGroupStore) teamMembersMinusGroupMembersQuery(teamID string, groupIDs []string, isCount bool) sq.SelectBuilder { 1260 var selectStr string 1261 1262 if isCount { 1263 selectStr = "count(DISTINCT Users.Id)" 1264 } else { 1265 tmpl := "Users.*, coalesce(TeamMembers.SchemeGuest, false), TeamMembers.SchemeAdmin, TeamMembers.SchemeUser, %s AS GroupIDs" 1266 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1267 selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") 1268 } else { 1269 selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") 1270 } 1271 } 1272 1273 subQuery := s.getQueryBuilder().Select("GroupMembers.UserId"). 1274 From("GroupMembers"). 1275 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1276 Where("GroupMembers.DeleteAt = 0"). 1277 Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '"))) 1278 1279 query, _ := subQuery.MustSql() 1280 1281 builder := s.getQueryBuilder().Select(selectStr). 1282 From("TeamMembers"). 1283 Join("Teams ON Teams.Id = TeamMembers.TeamId"). 1284 Join("Users ON Users.Id = TeamMembers.UserId"). 1285 LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId"). 1286 LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id"). 1287 LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1288 Where("TeamMembers.DeleteAt = 0"). 1289 Where("Teams.DeleteAt = 0"). 1290 Where("Users.DeleteAt = 0"). 1291 Where("Bots.UserId IS NULL"). 1292 Where("Teams.Id = ?", teamID). 1293 Where(fmt.Sprintf("Users.Id NOT IN (%s)", query)) 1294 1295 if !isCount { 1296 builder = builder.GroupBy("Users.Id, TeamMembers.SchemeGuest, TeamMembers.SchemeAdmin, TeamMembers.SchemeUser") 1297 } 1298 1299 return builder 1300 } 1301 1302 // TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given 1303 // groups. 1304 func (s *SqlGroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, error) { 1305 query := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, false) 1306 query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage)) 1307 1308 queryString, args, err := query.ToSql() 1309 if err != nil { 1310 return nil, errors.Wrap(err, "team_members_minus_group_members") 1311 } 1312 1313 var users []*model.UserWithGroups 1314 if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil { 1315 return nil, errors.Wrap(err, "failed to find UserWithGroups") 1316 } 1317 1318 return users, nil 1319 } 1320 1321 // CountTeamMembersMinusGroupMembers returns the count of the set of users on the given team minus the set of users 1322 // in the given groups. 1323 func (s *SqlGroupStore) CountTeamMembersMinusGroupMembers(teamID string, groupIDs []string) (int64, error) { 1324 queryString, args, err := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, true).ToSql() 1325 if err != nil { 1326 return 0, errors.Wrap(err, "count_team_members_minus_group_members_tosql") 1327 } 1328 1329 var count int64 1330 if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil { 1331 return 0, errors.Wrap(err, "failed to count TeamMembers minus GroupMembers") 1332 } 1333 1334 return count, nil 1335 } 1336 1337 func (s *SqlGroupStore) channelMembersMinusGroupMembersQuery(channelID string, groupIDs []string, isCount bool) sq.SelectBuilder { 1338 var selectStr string 1339 1340 if isCount { 1341 selectStr = "count(DISTINCT Users.Id)" 1342 } else { 1343 tmpl := "Users.*, coalesce(ChannelMembers.SchemeGuest, false), ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser, %s AS GroupIDs" 1344 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1345 selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") 1346 } else { 1347 selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") 1348 } 1349 } 1350 1351 subQuery := s.getQueryBuilder().Select("GroupMembers.UserId"). 1352 From("GroupMembers"). 1353 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1354 Where("GroupMembers.DeleteAt = 0"). 1355 Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '"))) 1356 1357 query, _ := subQuery.MustSql() 1358 1359 builder := s.getQueryBuilder().Select(selectStr). 1360 From("ChannelMembers"). 1361 Join("Channels ON Channels.Id = ChannelMembers.ChannelId"). 1362 Join("Users ON Users.Id = ChannelMembers.UserId"). 1363 LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId"). 1364 LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id"). 1365 LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1366 Where("Channels.DeleteAt = 0"). 1367 Where("Users.DeleteAt = 0"). 1368 Where("Bots.UserId IS NULL"). 1369 Where("Channels.Id = ?", channelID). 1370 Where(fmt.Sprintf("Users.Id NOT IN (%s)", query)) 1371 1372 if !isCount { 1373 builder = builder.GroupBy("Users.Id, ChannelMembers.SchemeGuest, ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser") 1374 } 1375 1376 return builder 1377 } 1378 1379 // ChannelMembersMinusGroupMembers returns the set of users in the given channel minus the set of users in the given 1380 // groups. 1381 func (s *SqlGroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, error) { 1382 query := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, false) 1383 query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage)) 1384 1385 queryString, args, err := query.ToSql() 1386 if err != nil { 1387 return nil, errors.Wrap(err, "channel_members_minus_group_members_tosql") 1388 } 1389 1390 var users []*model.UserWithGroups 1391 if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil { 1392 return nil, errors.Wrap(err, "failed to find UserWithGroups") 1393 } 1394 1395 return users, nil 1396 } 1397 1398 // CountChannelMembersMinusGroupMembers returns the count of the set of users in the given channel minus the set of users 1399 // in the given groups. 1400 func (s *SqlGroupStore) CountChannelMembersMinusGroupMembers(channelID string, groupIDs []string) (int64, error) { 1401 queryString, args, err := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, true).ToSql() 1402 if err != nil { 1403 return 0, errors.Wrap(err, "count_channel_members_minus_group_members_tosql") 1404 } 1405 1406 var count int64 1407 if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil { 1408 return 0, errors.Wrap(err, "failed to count ChannelMembers") 1409 } 1410 1411 return count, nil 1412 } 1413 1414 func (s *SqlGroupStore) AdminRoleGroupsForSyncableMember(userID, syncableID string, syncableType model.GroupSyncableType) ([]string, error) { 1415 var groupIds []string 1416 1417 query := fmt.Sprintf(` 1418 SELECT 1419 GroupMembers.GroupId 1420 FROM 1421 GroupMembers 1422 INNER JOIN 1423 Group%[1]ss ON Group%[1]ss.GroupId = GroupMembers.GroupId 1424 WHERE 1425 GroupMembers.UserId = :UserId 1426 AND GroupMembers.DeleteAt = 0 1427 AND %[1]sId = :%[1]sId 1428 AND Group%[1]ss.DeleteAt = 0 1429 AND Group%[1]ss.SchemeAdmin = TRUE`, syncableType) 1430 1431 _, err := s.GetReplica().Select(&groupIds, query, map[string]interface{}{"UserId": userID, fmt.Sprintf("%sId", syncableType): syncableID}) 1432 if err != nil { 1433 return nil, errors.Wrap(err, "failed to find Group ids") 1434 } 1435 1436 return groupIds, nil 1437 } 1438 1439 func (s *SqlGroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, error) { 1440 builder := s.getQueryBuilder().Select("UserId"). 1441 From(fmt.Sprintf("Group%ss", syncableType)). 1442 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) 1443 1444 query, args, err := builder.ToSql() 1445 if err != nil { 1446 return nil, errors.Wrap(err, "permitted_syncable_admins_tosql") 1447 } 1448 1449 var userIDs []string 1450 if _, err = s.GetReplica().Select(&userIDs, query, args...); err != nil { 1451 return nil, errors.Wrapf(err, "failed to find User ids") 1452 } 1453 1454 return userIDs, nil 1455 } 1456 1457 func (s *SqlGroupStore) GroupCount() (int64, error) { 1458 return s.countTable("UserGroups") 1459 } 1460 1461 func (s *SqlGroupStore) GroupTeamCount() (int64, error) { 1462 return s.countTable("GroupTeams") 1463 } 1464 1465 func (s *SqlGroupStore) GroupChannelCount() (int64, error) { 1466 return s.countTable("GroupChannels") 1467 } 1468 1469 func (s *SqlGroupStore) GroupMemberCount() (int64, error) { 1470 return s.countTable("GroupMembers") 1471 } 1472 1473 func (s *SqlGroupStore) DistinctGroupMemberCount() (int64, error) { 1474 return s.countTableWithSelectAndWhere("COUNT(DISTINCT UserId)", "GroupMembers", nil) 1475 } 1476 1477 func (s *SqlGroupStore) GroupCountWithAllowReference() (int64, error) { 1478 return s.countTableWithSelectAndWhere("COUNT(*)", "UserGroups", sq.Eq{"AllowReference": true, "DeleteAt": 0}) 1479 } 1480 1481 func (s *SqlGroupStore) countTable(tableName string) (int64, error) { 1482 return s.countTableWithSelectAndWhere("COUNT(*)", tableName, nil) 1483 } 1484 1485 func (s *SqlGroupStore) countTableWithSelectAndWhere(selectStr, tableName string, whereStmt map[string]interface{}) (int64, error) { 1486 if whereStmt == nil { 1487 whereStmt = sq.Eq{"DeleteAt": 0} 1488 } 1489 1490 query := s.getQueryBuilder().Select(selectStr).From(tableName).Where(whereStmt) 1491 1492 sql, args, err := query.ToSql() 1493 if err != nil { 1494 return 0, errors.Wrap(err, "count_table_with_select_and_where_tosql") 1495 } 1496 1497 count, err := s.GetReplica().SelectInt(sql, args...) 1498 if err != nil { 1499 return 0, errors.Wrapf(err, "failed to count from table %s", tableName) 1500 } 1501 1502 return count, nil 1503 }