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