github.com/mattermost/mattermost-server/v5@v5.39.3/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 DeleteAt: 0, 398 } 399 400 if err := member.IsValid(); err != nil { 401 return nil, err 402 } 403 404 var retrievedGroup *model.Group 405 if err := s.GetReplica().SelectOne(&retrievedGroup, "SELECT * FROM UserGroups WHERE Id = :Id", map[string]interface{}{"Id": groupID}); err != nil { 406 return nil, errors.Wrapf(err, "failed to get UserGroup with groupId=%s and userId=%s", groupID, userID) 407 } 408 409 query := s.getQueryBuilder(). 410 Insert("GroupMembers"). 411 Columns("GroupId", "UserId", "CreateAt", "DeleteAt"). 412 Values(member.GroupId, member.UserId, member.CreateAt, member.DeleteAt) 413 414 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 415 query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE CreateAt = ?, DeleteAt = ?", member.CreateAt, member.DeleteAt)) 416 } else if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 417 query = query.SuffixExpr(sq.Expr("ON CONFLICT (groupid, userid) DO UPDATE SET CreateAt = ?, DeleteAt = ?", member.CreateAt, member.DeleteAt)) 418 } 419 420 queryString, args, err := query.ToSql() 421 if err != nil { 422 return nil, errors.Wrap(err, "failed to generate sqlquery") 423 } 424 425 if _, err = s.GetMaster().Exec(queryString, args...); err != nil { 426 return nil, errors.Wrap(err, "failed to save GroupMember") 427 } 428 return member, nil 429 } 430 431 func (s *SqlGroupStore) DeleteMember(groupID string, userID string) (*model.GroupMember, error) { 432 var retrievedMember *model.GroupMember 433 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 { 434 if err == sql.ErrNoRows { 435 return nil, store.NewErrNotFound("GroupMember", fmt.Sprintf("groupId=%s, userId=%s", groupID, userID)) 436 } 437 return nil, errors.Wrapf(err, "failed to get GroupMember with groupId=%s and userId=%s", groupID, userID) 438 } 439 440 retrievedMember.DeleteAt = model.GetMillis() 441 442 if _, err := s.GetMaster().Update(retrievedMember); err != nil { 443 return nil, errors.Wrapf(err, "failed to update GroupMember with groupId=%s and userId=%s", groupID, userID) 444 } 445 446 return retrievedMember, nil 447 } 448 449 func (s *SqlGroupStore) PermanentDeleteMembersByUser(userId string) error { 450 if _, err := s.GetMaster().Exec("DELETE FROM GroupMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 451 return errors.Wrapf(err, "failed to permanent delete GroupMember with userId=%s", userId) 452 } 453 return nil 454 } 455 456 func (s *SqlGroupStore) CreateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, error) { 457 if err := groupSyncable.IsValid(); err != nil { 458 return nil, err 459 } 460 461 // Reset values that shouldn't be updatable by parameter 462 groupSyncable.DeleteAt = 0 463 groupSyncable.CreateAt = model.GetMillis() 464 groupSyncable.UpdateAt = groupSyncable.CreateAt 465 466 var insertErr error 467 468 switch groupSyncable.Type { 469 case model.GroupSyncableTypeTeam: 470 if _, err := s.Team().Get(groupSyncable.SyncableId); err != nil { 471 return nil, err 472 } 473 474 insertErr = s.GetMaster().Insert(groupSyncableToGroupTeam(groupSyncable)) 475 case model.GroupSyncableTypeChannel: 476 var channel *model.Channel 477 channel, err := s.Channel().Get(groupSyncable.SyncableId, false) 478 if err != nil { 479 return nil, err 480 } 481 insertErr = s.GetMaster().Insert(groupSyncableToGroupChannel(groupSyncable)) 482 groupSyncable.TeamID = channel.TeamId 483 default: 484 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 485 } 486 487 if insertErr != nil { 488 return nil, errors.Wrap(insertErr, "unable to insert GroupSyncable") 489 } 490 491 return groupSyncable, nil 492 } 493 494 func (s *SqlGroupStore) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 495 groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType) 496 if err != nil { 497 if err == sql.ErrNoRows { 498 return nil, store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType)) 499 } 500 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType) 501 } 502 503 return groupSyncable, nil 504 } 505 506 func (s *SqlGroupStore) getGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 507 var err error 508 var result interface{} 509 510 switch syncableType { 511 case model.GroupSyncableTypeTeam: 512 result, err = s.GetReplica().Get(groupTeam{}, groupID, syncableID) 513 case model.GroupSyncableTypeChannel: 514 result, err = s.GetReplica().Get(groupChannel{}, groupID, syncableID) 515 } 516 517 if err != nil { 518 return nil, err 519 } 520 521 if result == nil { 522 return nil, sql.ErrNoRows 523 } 524 525 groupSyncable := model.GroupSyncable{} 526 switch syncableType { 527 case model.GroupSyncableTypeTeam: 528 groupTeam := result.(*groupTeam) 529 groupSyncable.SyncableId = groupTeam.TeamId 530 groupSyncable.GroupId = groupTeam.GroupId 531 groupSyncable.AutoAdd = groupTeam.AutoAdd 532 groupSyncable.CreateAt = groupTeam.CreateAt 533 groupSyncable.DeleteAt = groupTeam.DeleteAt 534 groupSyncable.UpdateAt = groupTeam.UpdateAt 535 groupSyncable.Type = syncableType 536 case model.GroupSyncableTypeChannel: 537 groupChannel := result.(*groupChannel) 538 groupSyncable.SyncableId = groupChannel.ChannelId 539 groupSyncable.GroupId = groupChannel.GroupId 540 groupSyncable.AutoAdd = groupChannel.AutoAdd 541 groupSyncable.CreateAt = groupChannel.CreateAt 542 groupSyncable.DeleteAt = groupChannel.DeleteAt 543 groupSyncable.UpdateAt = groupChannel.UpdateAt 544 groupSyncable.Type = syncableType 545 default: 546 return nil, fmt.Errorf("unable to convert syncableType: %s", syncableType.String()) 547 } 548 549 return &groupSyncable, nil 550 } 551 552 func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableType model.GroupSyncableType) ([]*model.GroupSyncable, error) { 553 args := map[string]interface{}{"GroupId": groupID} 554 555 groupSyncables := []*model.GroupSyncable{} 556 557 switch syncableType { 558 case model.GroupSyncableTypeTeam: 559 sqlQuery := ` 560 SELECT 561 GroupTeams.*, 562 Teams.DisplayName AS TeamDisplayName, 563 Teams.Type AS TeamType 564 FROM 565 GroupTeams 566 JOIN Teams ON Teams.Id = GroupTeams.TeamId 567 WHERE 568 GroupId = :GroupId AND GroupTeams.DeleteAt = 0` 569 570 results := []*groupTeamJoin{} 571 _, err := s.GetReplica().Select(&results, sqlQuery, args) 572 if err != nil { 573 return nil, errors.Wrapf(err, "failed to find GroupTeams with groupId=%s", groupID) 574 } 575 for _, result := range results { 576 groupSyncable := &model.GroupSyncable{ 577 SyncableId: result.TeamId, 578 GroupId: result.GroupId, 579 AutoAdd: result.AutoAdd, 580 CreateAt: result.CreateAt, 581 DeleteAt: result.DeleteAt, 582 UpdateAt: result.UpdateAt, 583 Type: syncableType, 584 TeamDisplayName: result.TeamDisplayName, 585 TeamType: result.TeamType, 586 SchemeAdmin: result.SchemeAdmin, 587 } 588 groupSyncables = append(groupSyncables, groupSyncable) 589 } 590 case model.GroupSyncableTypeChannel: 591 sqlQuery := ` 592 SELECT 593 GroupChannels.*, 594 Channels.DisplayName AS ChannelDisplayName, 595 Teams.DisplayName AS TeamDisplayName, 596 Channels.Type As ChannelType, 597 Teams.Type As TeamType, 598 Teams.Id AS TeamId 599 FROM 600 GroupChannels 601 JOIN Channels ON Channels.Id = GroupChannels.ChannelId 602 JOIN Teams ON Teams.Id = Channels.TeamId 603 WHERE 604 GroupId = :GroupId AND GroupChannels.DeleteAt = 0` 605 606 results := []*groupChannelJoin{} 607 _, err := s.GetReplica().Select(&results, sqlQuery, args) 608 if err != nil { 609 return nil, errors.Wrapf(err, "failed to find GroupChannels with groupId=%s", groupID) 610 } 611 for _, result := range results { 612 groupSyncable := &model.GroupSyncable{ 613 SyncableId: result.ChannelId, 614 GroupId: result.GroupId, 615 AutoAdd: result.AutoAdd, 616 CreateAt: result.CreateAt, 617 DeleteAt: result.DeleteAt, 618 UpdateAt: result.UpdateAt, 619 Type: syncableType, 620 ChannelDisplayName: result.ChannelDisplayName, 621 ChannelType: result.ChannelType, 622 TeamDisplayName: result.TeamDisplayName, 623 TeamType: result.TeamType, 624 TeamID: result.TeamID, 625 SchemeAdmin: result.SchemeAdmin, 626 } 627 groupSyncables = append(groupSyncables, groupSyncable) 628 } 629 } 630 631 return groupSyncables, nil 632 } 633 634 func (s *SqlGroupStore) UpdateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, error) { 635 retrievedGroupSyncable, err := s.getGroupSyncable(groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type) 636 if err != nil { 637 if err == sql.ErrNoRows { 638 return nil, errors.Wrap(store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type)), "GroupSyncable not found") 639 } 640 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type) 641 } 642 643 if err := groupSyncable.IsValid(); err != nil { 644 return nil, err 645 } 646 647 // If updating DeleteAt it can only be to 0 648 if groupSyncable.DeleteAt != retrievedGroupSyncable.DeleteAt && groupSyncable.DeleteAt != 0 { 649 return nil, errors.New("DeleteAt should be 0 when updating") 650 } 651 652 // Reset these properties, don't update them based on input 653 groupSyncable.CreateAt = retrievedGroupSyncable.CreateAt 654 groupSyncable.UpdateAt = model.GetMillis() 655 656 switch groupSyncable.Type { 657 case model.GroupSyncableTypeTeam: 658 _, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable)) 659 case model.GroupSyncableTypeChannel: 660 // We need to get the TeamId so redux can manage channels when teams are unlinked 661 var channel *model.Channel 662 channel, channelErr := s.Channel().Get(groupSyncable.SyncableId, false) 663 if channelErr != nil { 664 return nil, channelErr 665 } 666 667 _, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable)) 668 669 groupSyncable.TeamID = channel.TeamId 670 default: 671 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 672 } 673 674 if err != nil { 675 return nil, errors.Wrap(err, "failed to update GroupSyncable") 676 } 677 678 return groupSyncable, nil 679 } 680 681 func (s *SqlGroupStore) DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) { 682 groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType) 683 if err != nil { 684 if err == sql.ErrNoRows { 685 return nil, store.NewErrNotFound("GroupSyncable", fmt.Sprintf("groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType)) 686 } 687 return nil, errors.Wrapf(err, "failed to find GroupSyncable with groupId=%s, syncableId=%s, syncableType=%s", groupID, syncableID, syncableType) 688 } 689 690 if groupSyncable.DeleteAt != 0 { 691 return nil, store.NewErrInvalidInput("GroupSyncable", "<groupId, syncableId, syncableType>", fmt.Sprintf("<%s, %s, %s>", groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type)) 692 } 693 694 time := model.GetMillis() 695 groupSyncable.DeleteAt = time 696 groupSyncable.UpdateAt = time 697 698 switch groupSyncable.Type { 699 case model.GroupSyncableTypeTeam: 700 _, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable)) 701 case model.GroupSyncableTypeChannel: 702 _, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable)) 703 default: 704 return nil, fmt.Errorf("invalid GroupSyncableType: %s", groupSyncable.Type) 705 } 706 707 if err != nil { 708 return nil, errors.Wrap(err, "failed to update GroupSyncable") 709 } 710 711 return groupSyncable, nil 712 } 713 714 func (s *SqlGroupStore) TeamMembersToAdd(since int64, teamID *string, includeRemovedMembers bool) ([]*model.UserTeamIDPair, error) { 715 builder := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupTeams.TeamId"). 716 From("GroupMembers"). 717 Join("GroupTeams ON GroupTeams.GroupId = GroupMembers.GroupId"). 718 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 719 Join("Teams ON Teams.Id = GroupTeams.TeamId"). 720 Where(sq.Eq{ 721 "UserGroups.DeleteAt": 0, 722 "GroupTeams.DeleteAt": 0, 723 "GroupTeams.AutoAdd": true, 724 "GroupMembers.DeleteAt": 0, 725 "Teams.DeleteAt": 0, 726 }) 727 728 if !includeRemovedMembers { 729 builder = builder. 730 JoinClause("LEFT OUTER JOIN TeamMembers ON TeamMembers.TeamId = GroupTeams.TeamId AND TeamMembers.UserId = GroupMembers.UserId"). 731 Where(sq.Eq{"TeamMembers.UserId": nil}). 732 Where(sq.Or{ 733 sq.GtOrEq{"GroupMembers.CreateAt": since}, 734 sq.GtOrEq{"GroupTeams.UpdateAt": since}, 735 }) 736 } 737 if teamID != nil { 738 builder = builder.Where(sq.Eq{"Teams.Id": *teamID}) 739 } 740 741 query, params, err := builder.ToSql() 742 if err != nil { 743 return nil, errors.Wrap(err, "team_members_to_add_tosql") 744 } 745 746 var teamMembers []*model.UserTeamIDPair 747 748 _, err = s.GetMaster().Select(&teamMembers, query, params...) 749 if err != nil { 750 return nil, errors.Wrap(err, "failed to find UserTeamIDPairs") 751 } 752 753 return teamMembers, nil 754 } 755 756 func (s *SqlGroupStore) ChannelMembersToAdd(since int64, channelID *string, includeRemovedMembers bool) ([]*model.UserChannelIDPair, error) { 757 builder := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupChannels.ChannelId"). 758 From("GroupMembers"). 759 Join("GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId"). 760 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 761 Join("Channels ON Channels.Id = GroupChannels.ChannelId"). 762 Where(sq.Eq{ 763 "UserGroups.DeleteAt": 0, 764 "GroupChannels.DeleteAt": 0, 765 "GroupChannels.AutoAdd": true, 766 "GroupMembers.DeleteAt": 0, 767 "Channels.DeleteAt": 0, 768 }) 769 770 if !includeRemovedMembers { 771 builder = builder. 772 JoinClause("LEFT OUTER JOIN ChannelMemberHistory ON ChannelMemberHistory.ChannelId = GroupChannels.ChannelId AND ChannelMemberHistory.UserId = GroupMembers.UserId"). 773 Where(sq.Eq{ 774 "ChannelMemberHistory.UserId": nil, 775 "ChannelMemberHistory.LeaveTime": nil, 776 }). 777 Where(sq.Or{ 778 sq.GtOrEq{"GroupMembers.CreateAt": since}, 779 sq.GtOrEq{"GroupChannels.UpdateAt": since}, 780 }) 781 } 782 if channelID != nil { 783 builder = builder.Where(sq.Eq{"Channels.Id": *channelID}) 784 } 785 786 query, params, err := builder.ToSql() 787 if err != nil { 788 return nil, errors.Wrap(err, "channel_members_to_add_tosql") 789 } 790 791 var channelMembers []*model.UserChannelIDPair 792 793 _, err = s.GetMaster().Select(&channelMembers, query, params...) 794 if err != nil { 795 return nil, errors.Wrap(err, "failed to find UserChannelIDPairs") 796 } 797 798 return channelMembers, nil 799 } 800 801 func groupSyncableToGroupTeam(groupSyncable *model.GroupSyncable) *groupTeam { 802 return &groupTeam{ 803 GroupSyncable: *groupSyncable, 804 TeamId: groupSyncable.SyncableId, 805 } 806 } 807 808 func groupSyncableToGroupChannel(groupSyncable *model.GroupSyncable) *groupChannel { 809 return &groupChannel{ 810 GroupSyncable: *groupSyncable, 811 ChannelId: groupSyncable.SyncableId, 812 } 813 } 814 815 func (s *SqlGroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, error) { 816 whereStmt := ` 817 (TeamMembers.TeamId, 818 TeamMembers.UserId) 819 NOT IN ( 820 SELECT 821 Teams.Id AS TeamId, 822 GroupMembers.UserId 823 FROM 824 Teams 825 JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id 826 JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId 827 JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id 828 WHERE 829 Teams.GroupConstrained = TRUE 830 AND GroupTeams.DeleteAt = 0 831 AND UserGroups.DeleteAt = 0 832 AND Teams.DeleteAt = 0 833 AND GroupMembers.DeleteAt = 0 834 GROUP BY 835 Teams.Id, 836 GroupMembers.UserId)` 837 838 builder := s.getQueryBuilder().Select( 839 "TeamMembers.TeamId", 840 "TeamMembers.UserId", 841 "TeamMembers.Roles", 842 "TeamMembers.DeleteAt", 843 "TeamMembers.SchemeUser", 844 "TeamMembers.SchemeAdmin", 845 "(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) AS SchemeGuest", 846 ). 847 From("TeamMembers"). 848 Join("Teams ON Teams.Id = TeamMembers.TeamId"). 849 LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId"). 850 Where(sq.Eq{"TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0, "Teams.GroupConstrained": true, "Bots.UserId": nil}). 851 Where(whereStmt) 852 853 if teamID != nil { 854 builder = builder.Where(sq.Eq{"TeamMembers.TeamId": *teamID}) 855 } 856 857 query, params, err := builder.ToSql() 858 if err != nil { 859 return nil, errors.Wrap(err, "team_members_to_remove_tosql") 860 } 861 862 var teamMembers []*model.TeamMember 863 864 _, err = s.GetReplica().Select(&teamMembers, query, params...) 865 if err != nil { 866 return nil, errors.Wrap(err, "failed to find TeamMembers") 867 } 868 869 return teamMembers, nil 870 } 871 872 func (s *SqlGroupStore) CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, error) { 873 countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectCountGroups, channelId, opts) 874 875 countQueryString, args, err := countQuery.ToSql() 876 if err != nil { 877 return int64(0), errors.Wrap(err, "count_groups_by_channel_tosql") 878 } 879 880 count, err := s.GetReplica().SelectInt(countQueryString, args...) 881 if err != nil { 882 return int64(0), errors.Wrapf(err, "failed to count Groups by channel with channelId=%s", channelId) 883 } 884 885 return count, nil 886 } 887 888 func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, error) { 889 query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectGroups, channelId, opts) 890 891 if opts.PageOpts != nil { 892 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 893 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 894 } 895 896 queryString, args, err := query.ToSql() 897 if err != nil { 898 return nil, errors.Wrap(err, "get_groups_by_channel_tosql") 899 } 900 901 var groups []*model.GroupWithSchemeAdmin 902 903 _, err = s.GetReplica().Select(&groups, queryString, args...) 904 if err != nil { 905 return nil, errors.Wrapf(err, "failed to find Groups with channelId=%s", channelId) 906 } 907 908 return groups, nil 909 } 910 911 func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, error) { 912 whereStmt := ` 913 (ChannelMembers.ChannelId, 914 ChannelMembers.UserId) 915 NOT IN ( 916 SELECT 917 Channels.Id AS ChannelId, 918 GroupMembers.UserId 919 FROM 920 Channels 921 JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id 922 JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId 923 JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id 924 WHERE 925 Channels.GroupConstrained = TRUE 926 AND GroupChannels.DeleteAt = 0 927 AND UserGroups.DeleteAt = 0 928 AND Channels.DeleteAt = 0 929 AND GroupMembers.DeleteAt = 0 930 GROUP BY 931 Channels.Id, 932 GroupMembers.UserId)` 933 934 builder := s.getQueryBuilder().Select( 935 "ChannelMembers.ChannelId", 936 "ChannelMembers.UserId", 937 "ChannelMembers.LastViewedAt", 938 "ChannelMembers.MsgCount", 939 "ChannelMembers.MsgCountRoot", 940 "ChannelMembers.MentionCount", 941 "ChannelMembers.MentionCountRoot", 942 "ChannelMembers.NotifyProps", 943 "ChannelMembers.LastUpdateAt", 944 "ChannelMembers.LastUpdateAt", 945 "ChannelMembers.SchemeUser", 946 "ChannelMembers.SchemeAdmin", 947 "(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) AS SchemeGuest", 948 ). 949 From("ChannelMembers"). 950 Join("Channels ON Channels.Id = ChannelMembers.ChannelId"). 951 LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId"). 952 Where(sq.Eq{"Channels.DeleteAt": 0, "Channels.GroupConstrained": true, "Bots.UserId": nil}). 953 Where(whereStmt) 954 955 if channelID != nil { 956 builder = builder.Where(sq.Eq{"ChannelMembers.ChannelId": *channelID}) 957 } 958 959 query, params, err := builder.ToSql() 960 if err != nil { 961 return nil, errors.Wrap(err, "channel_members_to_remove_tosql") 962 } 963 964 var channelMembers []*model.ChannelMember 965 966 _, err = s.GetReplica().Select(&channelMembers, query, params...) 967 if err != nil { 968 return nil, errors.Wrap(err, "failed to find ChannelMembers") 969 } 970 971 return channelMembers, nil 972 } 973 974 func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t selectType, syncableID string, opts model.GroupSearchOpts) sq.SelectBuilder { 975 selectStrs := map[selectType]string{ 976 selectGroups: "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin", 977 selectCountGroups: "COUNT(*)", 978 } 979 980 var table string 981 var idCol string 982 if st == model.GroupSyncableTypeTeam { 983 table = "GroupTeams" 984 idCol = "TeamId" 985 } else { 986 table = "GroupChannels" 987 idCol = "ChannelId" 988 } 989 990 query := s.getQueryBuilder(). 991 Select(selectStrs[t]). 992 From(fmt.Sprintf("%s gs", table)). 993 LeftJoin("UserGroups ug ON gs.GroupId = ug.Id"). 994 Where(fmt.Sprintf("ug.DeleteAt = 0 AND gs.%s = ? AND gs.DeleteAt = 0", idCol), syncableID) 995 996 if opts.IncludeMemberCount && t == selectGroups { 997 query = s.getQueryBuilder(). 998 Select(fmt.Sprintf("ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, Group%ss.SchemeAdmin AS SyncableSchemeAdmin", st)). 999 From("UserGroups ug"). 1000 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"). 1001 LeftJoin(fmt.Sprintf("%[1]s ON %[1]s.GroupId = ug.Id", table)). 1002 Where(fmt.Sprintf("ug.DeleteAt = 0 AND %[1]s.DeleteAt = 0 AND %[1]s.%[2]s = ?", table, idCol), syncableID). 1003 OrderBy("ug.DisplayName") 1004 } 1005 1006 if opts.FilterAllowReference && t == selectGroups { 1007 query = query.Where("ug.AllowReference = true") 1008 } 1009 1010 if opts.Q != "" { 1011 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 1012 operatorKeyword := "ILIKE" 1013 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1014 operatorKeyword = "LIKE" 1015 } 1016 query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 1017 } 1018 1019 return query 1020 } 1021 1022 func (s *SqlGroupStore) getGroupsAssociatedToChannelsByTeam(teamID string, opts model.GroupSearchOpts) sq.SelectBuilder { 1023 query := s.getQueryBuilder(). 1024 Select("gc.ChannelId, ug.*, gc.SchemeAdmin AS SyncableSchemeAdmin"). 1025 From("UserGroups ug"). 1026 LeftJoin(` 1027 (SELECT 1028 GroupChannels.GroupId, GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.SchemeAdmin 1029 FROM 1030 GroupChannels 1031 LEFT JOIN 1032 Channels ON (Channels.Id = GroupChannels.ChannelId) 1033 WHERE 1034 GroupChannels.DeleteAt = 0 1035 AND Channels.DeleteAt = 0 1036 AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID). 1037 Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0"). 1038 OrderBy("ug.DisplayName") 1039 1040 if opts.IncludeMemberCount { 1041 query = s.getQueryBuilder(). 1042 Select("gc.ChannelId, ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, gc.SchemeAdmin AS SyncableSchemeAdmin"). 1043 From("UserGroups ug"). 1044 LeftJoin(` 1045 (SELECT 1046 GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.GroupId, GroupChannels.SchemeAdmin 1047 FROM 1048 GroupChannels 1049 LEFT JOIN 1050 Channels ON (Channels.Id = GroupChannels.ChannelId) 1051 WHERE 1052 GroupChannels.DeleteAt = 0 1053 AND Channels.DeleteAt = 0 1054 AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID). 1055 LeftJoin(`( 1056 SELECT 1057 GroupMembers.GroupId, COUNT(*) AS MemberCount 1058 FROM 1059 GroupMembers 1060 LEFT JOIN 1061 Users ON Users.Id = GroupMembers.UserId 1062 WHERE 1063 GroupMembers.DeleteAt = 0 1064 AND Users.DeleteAt = 0 1065 GROUP BY GroupId) AS Members 1066 ON Members.GroupId = ug.Id`). 1067 Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0"). 1068 OrderBy("ug.DisplayName") 1069 } 1070 1071 if opts.FilterAllowReference { 1072 query = query.Where("ug.AllowReference = true") 1073 } 1074 1075 if opts.Q != "" { 1076 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 1077 operatorKeyword := "ILIKE" 1078 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1079 operatorKeyword = "LIKE" 1080 } 1081 query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 1082 } 1083 1084 return query 1085 } 1086 1087 func (s *SqlGroupStore) CountGroupsByTeam(teamId string, opts model.GroupSearchOpts) (int64, error) { 1088 countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectCountGroups, teamId, opts) 1089 1090 countQueryString, args, err := countQuery.ToSql() 1091 if err != nil { 1092 return int64(0), errors.Wrap(err, "count_groups_by_team_tosql") 1093 } 1094 1095 count, err := s.GetReplica().SelectInt(countQueryString, args...) 1096 if err != nil { 1097 return int64(0), errors.Wrapf(err, "failed to count Groups with teamId=%s", teamId) 1098 } 1099 1100 return count, nil 1101 } 1102 1103 func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, error) { 1104 query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectGroups, teamId, opts) 1105 1106 if opts.PageOpts != nil { 1107 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 1108 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 1109 } 1110 1111 queryString, args, err := query.ToSql() 1112 if err != nil { 1113 return nil, errors.Wrap(err, "get_groups_by_team_tosql") 1114 } 1115 1116 var groups []*model.GroupWithSchemeAdmin 1117 1118 _, err = s.GetReplica().Select(&groups, queryString, args...) 1119 if err != nil { 1120 return nil, errors.Wrapf(err, "failed to find Groups with teamId=%s", teamId) 1121 } 1122 1123 return groups, nil 1124 } 1125 1126 func (s *SqlGroupStore) GetGroupsAssociatedToChannelsByTeam(teamId string, opts model.GroupSearchOpts) (map[string][]*model.GroupWithSchemeAdmin, error) { 1127 query := s.getGroupsAssociatedToChannelsByTeam(teamId, opts) 1128 1129 if opts.PageOpts != nil { 1130 offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage) 1131 query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset) 1132 } 1133 1134 queryString, args, err := query.ToSql() 1135 if err != nil { 1136 return nil, errors.Wrap(err, "get_groups_associated_to_channel_by_team_tosql") 1137 } 1138 1139 var tgroups []*model.GroupsAssociatedToChannelWithSchemeAdmin 1140 1141 _, err = s.GetReplica().Select(&tgroups, queryString, args...) 1142 if err != nil { 1143 return nil, errors.Wrapf(err, "failed to find Groups with teamId=%s", teamId) 1144 } 1145 1146 groups := map[string][]*model.GroupWithSchemeAdmin{} 1147 for _, tgroup := range tgroups { 1148 var group = model.GroupWithSchemeAdmin{} 1149 group.Group = tgroup.Group 1150 group.SchemeAdmin = tgroup.SchemeAdmin 1151 1152 if val, ok := groups[tgroup.ChannelId]; ok { 1153 groups[tgroup.ChannelId] = append(val, &group) 1154 } else { 1155 groups[tgroup.ChannelId] = []*model.GroupWithSchemeAdmin{&group} 1156 } 1157 } 1158 1159 return groups, nil 1160 } 1161 1162 func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, error) { 1163 var groups []*model.Group 1164 1165 groupsQuery := s.getQueryBuilder().Select("g.*") 1166 1167 if opts.IncludeMemberCount { 1168 groupsQuery = s.getQueryBuilder(). 1169 Select("g.*, coalesce(Members.MemberCount, 0) AS MemberCount"). 1170 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") 1171 } 1172 1173 groupsQuery = groupsQuery. 1174 From("UserGroups g"). 1175 OrderBy("g.DisplayName") 1176 1177 if opts.Since > 0 { 1178 groupsQuery = groupsQuery.Where(sq.Gt{ 1179 "g.UpdateAt": opts.Since, 1180 }) 1181 } else { 1182 groupsQuery = groupsQuery.Where("g.DeleteAt = 0") 1183 } 1184 1185 if perPage != 0 { 1186 groupsQuery = groupsQuery. 1187 Limit(uint64(perPage)). 1188 Offset(uint64(page * perPage)) 1189 } 1190 1191 if opts.FilterAllowReference { 1192 groupsQuery = groupsQuery.Where("g.AllowReference = true") 1193 } 1194 1195 if opts.Q != "" { 1196 pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\")) 1197 operatorKeyword := "ILIKE" 1198 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1199 operatorKeyword = "LIKE" 1200 } 1201 groupsQuery = groupsQuery.Where(fmt.Sprintf("(g.Name %[1]s ? OR g.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) 1202 } 1203 1204 if len(opts.NotAssociatedToTeam) == 26 { 1205 groupsQuery = groupsQuery.Where(` 1206 g.Id NOT IN ( 1207 SELECT 1208 Id 1209 FROM 1210 UserGroups 1211 JOIN GroupTeams ON GroupTeams.GroupId = UserGroups.Id 1212 WHERE 1213 GroupTeams.DeleteAt = 0 1214 AND UserGroups.DeleteAt = 0 1215 AND GroupTeams.TeamId = ? 1216 ) 1217 `, opts.NotAssociatedToTeam) 1218 } 1219 1220 if len(opts.NotAssociatedToChannel) == 26 { 1221 groupsQuery = groupsQuery.Where(` 1222 g.Id NOT IN ( 1223 SELECT 1224 Id 1225 FROM 1226 UserGroups 1227 JOIN GroupChannels ON GroupChannels.GroupId = UserGroups.Id 1228 WHERE 1229 GroupChannels.DeleteAt = 0 1230 AND UserGroups.DeleteAt = 0 1231 AND GroupChannels.ChannelId = ? 1232 ) 1233 `, opts.NotAssociatedToChannel) 1234 } 1235 1236 if opts.FilterParentTeamPermitted && len(opts.NotAssociatedToChannel) == 26 { 1237 groupsQuery = groupsQuery.Where(` 1238 CASE 1239 WHEN ( 1240 SELECT 1241 Teams.GroupConstrained 1242 FROM 1243 Teams 1244 JOIN Channels ON Channels.TeamId = Teams.Id 1245 WHERE 1246 Channels.Id = ? 1247 ) THEN g.Id IN ( 1248 SELECT 1249 GroupId 1250 FROM 1251 GroupTeams 1252 WHERE 1253 GroupTeams.DeleteAt = 0 1254 AND GroupTeams.TeamId = ( 1255 SELECT 1256 TeamId 1257 FROM 1258 Channels 1259 WHERE 1260 Id = ? 1261 ) 1262 ) 1263 ELSE TRUE 1264 END 1265 `, opts.NotAssociatedToChannel, opts.NotAssociatedToChannel) 1266 } 1267 1268 queryString, args, err := groupsQuery.ToSql() 1269 if err != nil { 1270 return nil, errors.Wrap(err, "get_groups_tosql") 1271 } 1272 1273 if _, err = s.GetReplica().Select(&groups, queryString, args...); err != nil { 1274 return nil, errors.Wrap(err, "failed to find Groups") 1275 } 1276 1277 return groups, nil 1278 } 1279 1280 func (s *SqlGroupStore) teamMembersMinusGroupMembersQuery(teamID string, groupIDs []string, isCount bool) sq.SelectBuilder { 1281 var selectStr string 1282 1283 if isCount { 1284 selectStr = "count(DISTINCT Users.Id)" 1285 } else { 1286 tmpl := "Users.*, coalesce(TeamMembers.SchemeGuest, false), TeamMembers.SchemeAdmin, TeamMembers.SchemeUser, %s AS GroupIDs" 1287 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1288 selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") 1289 } else { 1290 selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") 1291 } 1292 } 1293 1294 subQuery := s.getQueryBuilder().Select("GroupMembers.UserId"). 1295 From("GroupMembers"). 1296 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1297 Where("GroupMembers.DeleteAt = 0"). 1298 Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '"))) 1299 1300 query, _ := subQuery.MustSql() 1301 1302 builder := s.getQueryBuilder().Select(selectStr). 1303 From("TeamMembers"). 1304 Join("Teams ON Teams.Id = TeamMembers.TeamId"). 1305 Join("Users ON Users.Id = TeamMembers.UserId"). 1306 LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId"). 1307 LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id"). 1308 LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1309 Where("TeamMembers.DeleteAt = 0"). 1310 Where("Teams.DeleteAt = 0"). 1311 Where("Users.DeleteAt = 0"). 1312 Where("Bots.UserId IS NULL"). 1313 Where("Teams.Id = ?", teamID). 1314 Where(fmt.Sprintf("Users.Id NOT IN (%s)", query)) 1315 1316 if !isCount { 1317 builder = builder.GroupBy("Users.Id, TeamMembers.SchemeGuest, TeamMembers.SchemeAdmin, TeamMembers.SchemeUser") 1318 } 1319 1320 return builder 1321 } 1322 1323 // TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given 1324 // groups. 1325 func (s *SqlGroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, error) { 1326 query := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, false) 1327 query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage)) 1328 1329 queryString, args, err := query.ToSql() 1330 if err != nil { 1331 return nil, errors.Wrap(err, "team_members_minus_group_members") 1332 } 1333 1334 var users []*model.UserWithGroups 1335 if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil { 1336 return nil, errors.Wrap(err, "failed to find UserWithGroups") 1337 } 1338 1339 return users, nil 1340 } 1341 1342 // CountTeamMembersMinusGroupMembers returns the count of the set of users on the given team minus the set of users 1343 // in the given groups. 1344 func (s *SqlGroupStore) CountTeamMembersMinusGroupMembers(teamID string, groupIDs []string) (int64, error) { 1345 queryString, args, err := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, true).ToSql() 1346 if err != nil { 1347 return 0, errors.Wrap(err, "count_team_members_minus_group_members_tosql") 1348 } 1349 1350 var count int64 1351 if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil { 1352 return 0, errors.Wrap(err, "failed to count TeamMembers minus GroupMembers") 1353 } 1354 1355 return count, nil 1356 } 1357 1358 func (s *SqlGroupStore) channelMembersMinusGroupMembersQuery(channelID string, groupIDs []string, isCount bool) sq.SelectBuilder { 1359 var selectStr string 1360 1361 if isCount { 1362 selectStr = "count(DISTINCT Users.Id)" 1363 } else { 1364 tmpl := "Users.*, coalesce(ChannelMembers.SchemeGuest, false), ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser, %s AS GroupIDs" 1365 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1366 selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") 1367 } else { 1368 selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") 1369 } 1370 } 1371 1372 subQuery := s.getQueryBuilder().Select("GroupMembers.UserId"). 1373 From("GroupMembers"). 1374 Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1375 Where("GroupMembers.DeleteAt = 0"). 1376 Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '"))) 1377 1378 query, _ := subQuery.MustSql() 1379 1380 builder := s.getQueryBuilder().Select(selectStr). 1381 From("ChannelMembers"). 1382 Join("Channels ON Channels.Id = ChannelMembers.ChannelId"). 1383 Join("Users ON Users.Id = ChannelMembers.UserId"). 1384 LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId"). 1385 LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id"). 1386 LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId"). 1387 Where("Channels.DeleteAt = 0"). 1388 Where("Users.DeleteAt = 0"). 1389 Where("Bots.UserId IS NULL"). 1390 Where("Channels.Id = ?", channelID). 1391 Where(fmt.Sprintf("Users.Id NOT IN (%s)", query)) 1392 1393 if !isCount { 1394 builder = builder.GroupBy("Users.Id, ChannelMembers.SchemeGuest, ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser") 1395 } 1396 1397 return builder 1398 } 1399 1400 // ChannelMembersMinusGroupMembers returns the set of users in the given channel minus the set of users in the given 1401 // groups. 1402 func (s *SqlGroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, error) { 1403 query := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, false) 1404 query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage)) 1405 1406 queryString, args, err := query.ToSql() 1407 if err != nil { 1408 return nil, errors.Wrap(err, "channel_members_minus_group_members_tosql") 1409 } 1410 1411 var users []*model.UserWithGroups 1412 if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil { 1413 return nil, errors.Wrap(err, "failed to find UserWithGroups") 1414 } 1415 1416 return users, nil 1417 } 1418 1419 // CountChannelMembersMinusGroupMembers returns the count of the set of users in the given channel minus the set of users 1420 // in the given groups. 1421 func (s *SqlGroupStore) CountChannelMembersMinusGroupMembers(channelID string, groupIDs []string) (int64, error) { 1422 queryString, args, err := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, true).ToSql() 1423 if err != nil { 1424 return 0, errors.Wrap(err, "count_channel_members_minus_group_members_tosql") 1425 } 1426 1427 var count int64 1428 if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil { 1429 return 0, errors.Wrap(err, "failed to count ChannelMembers") 1430 } 1431 1432 return count, nil 1433 } 1434 1435 func (s *SqlGroupStore) AdminRoleGroupsForSyncableMember(userID, syncableID string, syncableType model.GroupSyncableType) ([]string, error) { 1436 var groupIds []string 1437 1438 query := fmt.Sprintf(` 1439 SELECT 1440 GroupMembers.GroupId 1441 FROM 1442 GroupMembers 1443 INNER JOIN 1444 Group%[1]ss ON Group%[1]ss.GroupId = GroupMembers.GroupId 1445 WHERE 1446 GroupMembers.UserId = :UserId 1447 AND GroupMembers.DeleteAt = 0 1448 AND %[1]sId = :%[1]sId 1449 AND Group%[1]ss.DeleteAt = 0 1450 AND Group%[1]ss.SchemeAdmin = TRUE`, syncableType) 1451 1452 _, err := s.GetReplica().Select(&groupIds, query, map[string]interface{}{"UserId": userID, fmt.Sprintf("%sId", syncableType): syncableID}) 1453 if err != nil { 1454 return nil, errors.Wrap(err, "failed to find Group ids") 1455 } 1456 1457 return groupIds, nil 1458 } 1459 1460 func (s *SqlGroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, error) { 1461 builder := s.getQueryBuilder().Select("UserId"). 1462 From(fmt.Sprintf("Group%ss", syncableType)). 1463 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) 1464 1465 query, args, err := builder.ToSql() 1466 if err != nil { 1467 return nil, errors.Wrap(err, "permitted_syncable_admins_tosql") 1468 } 1469 1470 var userIDs []string 1471 if _, err = s.GetMaster().Select(&userIDs, query, args...); err != nil { 1472 return nil, errors.Wrapf(err, "failed to find User ids") 1473 } 1474 1475 return userIDs, nil 1476 } 1477 1478 func (s *SqlGroupStore) GroupCount() (int64, error) { 1479 return s.countTable("UserGroups") 1480 } 1481 1482 func (s *SqlGroupStore) GroupTeamCount() (int64, error) { 1483 return s.countTable("GroupTeams") 1484 } 1485 1486 func (s *SqlGroupStore) GroupChannelCount() (int64, error) { 1487 return s.countTable("GroupChannels") 1488 } 1489 1490 func (s *SqlGroupStore) GroupMemberCount() (int64, error) { 1491 return s.countTable("GroupMembers") 1492 } 1493 1494 func (s *SqlGroupStore) DistinctGroupMemberCount() (int64, error) { 1495 return s.countTableWithSelectAndWhere("COUNT(DISTINCT UserId)", "GroupMembers", nil) 1496 } 1497 1498 func (s *SqlGroupStore) GroupCountWithAllowReference() (int64, error) { 1499 return s.countTableWithSelectAndWhere("COUNT(*)", "UserGroups", sq.Eq{"AllowReference": true, "DeleteAt": 0}) 1500 } 1501 1502 func (s *SqlGroupStore) countTable(tableName string) (int64, error) { 1503 return s.countTableWithSelectAndWhere("COUNT(*)", tableName, nil) 1504 } 1505 1506 func (s *SqlGroupStore) countTableWithSelectAndWhere(selectStr, tableName string, whereStmt map[string]interface{}) (int64, error) { 1507 if whereStmt == nil { 1508 whereStmt = sq.Eq{"DeleteAt": 0} 1509 } 1510 1511 query := s.getQueryBuilder().Select(selectStr).From(tableName).Where(whereStmt) 1512 1513 sql, args, err := query.ToSql() 1514 if err != nil { 1515 return 0, errors.Wrap(err, "count_table_with_select_and_where_tosql") 1516 } 1517 1518 count, err := s.GetReplica().SelectInt(sql, args...) 1519 if err != nil { 1520 return 0, errors.Wrapf(err, "failed to count from table %s", tableName) 1521 } 1522 1523 return count, nil 1524 }