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