github.com/crspeller/mattermost-server@v0.0.0-20190328001957-a200beb3d111/store/sqlstore/team_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 "net/http" 9 "strconv" 10 "strings" 11 12 "github.com/mattermost/gorp" 13 "github.com/crspeller/mattermost-server/model" 14 "github.com/crspeller/mattermost-server/store" 15 ) 16 17 const ( 18 TEAM_MEMBER_EXISTS_ERROR = "store.sql_team.save_member.exists.app_error" 19 ) 20 21 type SqlTeamStore struct { 22 SqlStore 23 } 24 25 type teamMember struct { 26 TeamId string 27 UserId string 28 Roles string 29 DeleteAt int64 30 SchemeUser sql.NullBool 31 SchemeAdmin sql.NullBool 32 } 33 34 func NewTeamMemberFromModel(tm *model.TeamMember) *teamMember { 35 return &teamMember{ 36 TeamId: tm.TeamId, 37 UserId: tm.UserId, 38 Roles: tm.ExplicitRoles, 39 DeleteAt: tm.DeleteAt, 40 SchemeUser: sql.NullBool{Valid: true, Bool: tm.SchemeUser}, 41 SchemeAdmin: sql.NullBool{Valid: true, Bool: tm.SchemeAdmin}, 42 } 43 } 44 45 type teamMemberWithSchemeRoles struct { 46 TeamId string 47 UserId string 48 Roles string 49 DeleteAt int64 50 SchemeUser sql.NullBool 51 SchemeAdmin sql.NullBool 52 TeamSchemeDefaultUserRole sql.NullString 53 TeamSchemeDefaultAdminRole sql.NullString 54 } 55 56 type teamMemberWithSchemeRolesList []teamMemberWithSchemeRoles 57 58 func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember { 59 var roles []string 60 var explicitRoles []string 61 62 // Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude 63 // them from ExplicitRoles field. 64 schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool 65 schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool 66 for _, role := range strings.Fields(db.Roles) { 67 isImplicit := false 68 if role == model.TEAM_USER_ROLE_ID { 69 // We have an implicit role via the system scheme. Override the "schemeUser" field to true. 70 schemeUser = true 71 isImplicit = true 72 } else if role == model.TEAM_ADMIN_ROLE_ID { 73 // We have an implicit role via the system scheme. 74 schemeAdmin = true 75 isImplicit = true 76 } 77 78 if !isImplicit { 79 explicitRoles = append(explicitRoles, role) 80 } 81 roles = append(roles, role) 82 } 83 84 // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add 85 // them to the Roles field for backwards compatibility reasons. 86 var schemeImpliedRoles []string 87 if db.SchemeUser.Valid && db.SchemeUser.Bool { 88 if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" { 89 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String) 90 } else { 91 schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_USER_ROLE_ID) 92 } 93 } 94 if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool { 95 if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" { 96 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String) 97 } else { 98 schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_ADMIN_ROLE_ID) 99 } 100 } 101 for _, impliedRole := range schemeImpliedRoles { 102 alreadyThere := false 103 for _, role := range roles { 104 if role == impliedRole { 105 alreadyThere = true 106 } 107 } 108 if !alreadyThere { 109 roles = append(roles, impliedRole) 110 } 111 } 112 113 tm := &model.TeamMember{ 114 TeamId: db.TeamId, 115 UserId: db.UserId, 116 Roles: strings.Join(roles, " "), 117 DeleteAt: db.DeleteAt, 118 SchemeUser: schemeUser, 119 SchemeAdmin: schemeAdmin, 120 ExplicitRoles: strings.Join(explicitRoles, " "), 121 } 122 return tm 123 } 124 125 func (db teamMemberWithSchemeRolesList) ToModel() []*model.TeamMember { 126 tms := make([]*model.TeamMember, 0) 127 128 for _, tm := range db { 129 tms = append(tms, tm.ToModel()) 130 } 131 132 return tms 133 } 134 135 func NewSqlTeamStore(sqlStore SqlStore) store.TeamStore { 136 s := &SqlTeamStore{sqlStore} 137 138 for _, db := range sqlStore.GetAllConns() { 139 table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id") 140 table.ColMap("Id").SetMaxSize(26) 141 table.ColMap("DisplayName").SetMaxSize(64) 142 table.ColMap("Name").SetMaxSize(64).SetUnique(true) 143 table.ColMap("Description").SetMaxSize(255) 144 table.ColMap("Email").SetMaxSize(128) 145 table.ColMap("CompanyName").SetMaxSize(64) 146 table.ColMap("AllowedDomains").SetMaxSize(500) 147 table.ColMap("InviteId").SetMaxSize(32) 148 149 tablem := db.AddTableWithName(teamMember{}, "TeamMembers").SetKeys(false, "TeamId", "UserId") 150 tablem.ColMap("TeamId").SetMaxSize(26) 151 tablem.ColMap("UserId").SetMaxSize(26) 152 tablem.ColMap("Roles").SetMaxSize(64) 153 } 154 155 return s 156 } 157 158 func (s SqlTeamStore) CreateIndexesIfNotExists() { 159 s.CreateIndexIfNotExists("idx_teams_name", "Teams", "Name") 160 s.RemoveIndexIfExists("idx_teams_description", "Teams") 161 s.CreateIndexIfNotExists("idx_teams_invite_id", "Teams", "InviteId") 162 s.CreateIndexIfNotExists("idx_teams_update_at", "Teams", "UpdateAt") 163 s.CreateIndexIfNotExists("idx_teams_create_at", "Teams", "CreateAt") 164 s.CreateIndexIfNotExists("idx_teams_delete_at", "Teams", "DeleteAt") 165 166 s.CreateIndexIfNotExists("idx_teammembers_team_id", "TeamMembers", "TeamId") 167 s.CreateIndexIfNotExists("idx_teammembers_user_id", "TeamMembers", "UserId") 168 s.CreateIndexIfNotExists("idx_teammembers_delete_at", "TeamMembers", "DeleteAt") 169 } 170 171 func (s SqlTeamStore) Save(team *model.Team) store.StoreChannel { 172 return store.Do(func(result *store.StoreResult) { 173 if len(team.Id) > 0 { 174 result.Err = model.NewAppError("SqlTeamStore.Save", 175 "store.sql_team.save.existing.app_error", nil, "id="+team.Id, http.StatusBadRequest) 176 return 177 } 178 179 team.PreSave() 180 181 if result.Err = team.IsValid(); result.Err != nil { 182 return 183 } 184 185 if err := s.GetMaster().Insert(team); err != nil { 186 if IsUniqueConstraintError(err, []string{"Name", "teams_name_key"}) { 187 result.Err = model.NewAppError("SqlTeamStore.Save", "store.sql_team.save.domain_exists.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusBadRequest) 188 return 189 } 190 result.Err = model.NewAppError("SqlTeamStore.Save", "store.sql_team.save.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError) 191 return 192 } 193 result.Data = team 194 }) 195 } 196 197 func (s SqlTeamStore) Update(team *model.Team) store.StoreChannel { 198 return store.Do(func(result *store.StoreResult) { 199 team.PreUpdate() 200 201 if result.Err = team.IsValid(); result.Err != nil { 202 return 203 } 204 205 oldResult, err := s.GetMaster().Get(model.Team{}, team.Id) 206 if err != nil { 207 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.finding.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError) 208 return 209 } 210 211 if oldResult == nil { 212 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.find.app_error", nil, "id="+team.Id, http.StatusBadRequest) 213 return 214 } 215 216 oldTeam := oldResult.(*model.Team) 217 team.CreateAt = oldTeam.CreateAt 218 team.UpdateAt = model.GetMillis() 219 220 count, err := s.GetMaster().Update(team) 221 if err != nil { 222 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.updating.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError) 223 return 224 } 225 if count != 1 { 226 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.app_error", nil, "id="+team.Id, http.StatusInternalServerError) 227 return 228 } 229 230 result.Data = team 231 }) 232 } 233 234 func (s SqlTeamStore) UpdateDisplayName(name string, teamId string) store.StoreChannel { 235 return store.Do(func(result *store.StoreResult) { 236 if _, err := s.GetMaster().Exec("UPDATE Teams SET DisplayName = :Name WHERE Id = :Id", map[string]interface{}{"Name": name, "Id": teamId}); err != nil { 237 result.Err = model.NewAppError("SqlTeamStore.UpdateName", "store.sql_team.update_display_name.app_error", nil, "team_id="+teamId, http.StatusInternalServerError) 238 return 239 } 240 241 result.Data = teamId 242 }) 243 } 244 245 func (s SqlTeamStore) Get(id string) store.StoreChannel { 246 return store.Do(func(result *store.StoreResult) { 247 obj, err := s.GetReplica().Get(model.Team{}, id) 248 if err != nil { 249 result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.finding.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 250 return 251 } 252 if obj == nil { 253 result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.find.app_error", nil, "id="+id, http.StatusNotFound) 254 return 255 } 256 257 team := obj.(*model.Team) 258 if len(team.InviteId) == 0 { 259 team.InviteId = team.Id 260 } 261 262 result.Data = team 263 }) 264 } 265 266 func (s SqlTeamStore) GetByInviteId(inviteId string) store.StoreChannel { 267 return store.Do(func(result *store.StoreResult) { 268 team := model.Team{} 269 270 if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Id = :InviteId OR InviteId = :InviteId", map[string]interface{}{"InviteId": inviteId}); err != nil { 271 result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.finding.app_error", nil, "inviteId="+inviteId+", "+err.Error(), http.StatusNotFound) 272 return 273 } 274 275 if len(team.InviteId) == 0 { 276 team.InviteId = team.Id 277 } 278 279 if len(inviteId) == 0 || team.InviteId != inviteId { 280 result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.find.app_error", nil, "inviteId="+inviteId, http.StatusNotFound) 281 return 282 } 283 284 result.Data = &team 285 }) 286 } 287 288 func (s SqlTeamStore) GetByName(name string) store.StoreChannel { 289 return store.Do(func(result *store.StoreResult) { 290 team := model.Team{} 291 292 if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil { 293 result.Err = model.NewAppError("SqlTeamStore.GetByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError) 294 return 295 } 296 297 if len(team.InviteId) == 0 { 298 team.InviteId = team.Id 299 } 300 301 result.Data = &team 302 }) 303 } 304 305 func (s SqlTeamStore) SearchByName(name string) store.StoreChannel { 306 return store.Do(func(result *store.StoreResult) { 307 var teams []*model.Team 308 309 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Name", map[string]interface{}{"Name": name + "%"}); err != nil { 310 result.Err = model.NewAppError("SqlTeamStore.SearchByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError) 311 return 312 } 313 314 result.Data = teams 315 }) 316 } 317 318 func (s SqlTeamStore) SearchAll(term string) store.StoreChannel { 319 return store.Do(func(result *store.StoreResult) { 320 var teams []*model.Team 321 322 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Term OR DisplayName LIKE :Term", map[string]interface{}{"Term": term + "%"}); err != nil { 323 result.Err = model.NewAppError("SqlTeamStore.SearchAll", "store.sql_team.search_all_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 324 return 325 } 326 327 result.Data = teams 328 }) 329 } 330 331 func (s SqlTeamStore) SearchOpen(term string) store.StoreChannel { 332 return store.Do(func(result *store.StoreResult) { 333 var teams []*model.Team 334 335 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Type = 'O' AND AllowOpenInvite = true AND (Name LIKE :Term OR DisplayName LIKE :Term)", map[string]interface{}{"Term": term + "%"}); err != nil { 336 result.Err = model.NewAppError("SqlTeamStore.SearchOpen", "store.sql_team.search_open_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 337 return 338 } 339 340 result.Data = teams 341 }) 342 } 343 344 func (s SqlTeamStore) SearchPrivate(term string) store.StoreChannel { 345 return store.Do(func(result *store.StoreResult) { 346 var teams []*model.Team 347 348 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE (Type != 'O' OR AllowOpenInvite = false) AND (Name LIKE :Term OR DisplayName LIKE :Term)", map[string]interface{}{"Term": term + "%"}); err != nil { 349 result.Err = model.NewAppError("SqlTeamStore.SearchPrivate", "store.sql_team.search_private_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 350 return 351 } 352 353 result.Data = teams 354 }) 355 } 356 357 func (s SqlTeamStore) GetAll() store.StoreChannel { 358 return store.Do(func(result *store.StoreResult) { 359 var data []*model.Team 360 if _, err := s.GetReplica().Select(&data, "SELECT * FROM Teams ORDER BY DisplayName"); err != nil { 361 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 362 return 363 } 364 365 for _, team := range data { 366 if len(team.InviteId) == 0 { 367 team.InviteId = team.Id 368 } 369 } 370 371 result.Data = data 372 }) 373 } 374 375 func (s SqlTeamStore) GetAllPage(offset int, limit int) store.StoreChannel { 376 return store.Do(func(result *store.StoreResult) { 377 var data []*model.Team 378 if _, err := s.GetReplica().Select(&data, "SELECT * FROM Teams ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 379 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 380 return 381 } 382 383 for _, team := range data { 384 if len(team.InviteId) == 0 { 385 team.InviteId = team.Id 386 } 387 } 388 389 result.Data = data 390 }) 391 } 392 393 func (s SqlTeamStore) GetTeamsByUserId(userId string) store.StoreChannel { 394 return store.Do(func(result *store.StoreResult) { 395 var data []*model.Team 396 if _, err := s.GetReplica().Select(&data, "SELECT Teams.* FROM Teams, TeamMembers WHERE TeamMembers.TeamId = Teams.Id AND TeamMembers.UserId = :UserId AND TeamMembers.DeleteAt = 0 AND Teams.DeleteAt = 0", map[string]interface{}{"UserId": userId}); err != nil { 397 result.Err = model.NewAppError("SqlTeamStore.GetTeamsByUserId", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 398 return 399 } 400 401 for _, team := range data { 402 if len(team.InviteId) == 0 { 403 team.InviteId = team.Id 404 } 405 } 406 407 result.Data = data 408 }) 409 } 410 411 func (s SqlTeamStore) GetAllPrivateTeamListing() store.StoreChannel { 412 return store.Do(func(result *store.StoreResult) { 413 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 0 ORDER BY DisplayName" 414 415 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 416 query = "SELECT * FROM Teams WHERE AllowOpenInvite = false ORDER BY DisplayName" 417 } 418 419 var data []*model.Team 420 if _, err := s.GetReplica().Select(&data, query); err != nil { 421 result.Err = model.NewAppError("SqlTeamStore.GetAllPrivateTeamListing", "store.sql_team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 422 return 423 } 424 425 for _, team := range data { 426 if len(team.InviteId) == 0 { 427 team.InviteId = team.Id 428 } 429 } 430 431 result.Data = data 432 }) 433 } 434 435 func (s SqlTeamStore) GetAllPrivateTeamPageListing(offset int, limit int) store.StoreChannel { 436 return store.Do(func(result *store.StoreResult) { 437 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset" 438 439 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 440 query = "SELECT * FROM Teams WHERE AllowOpenInvite = false ORDER BY DisplayName LIMIT :Limit OFFSET :Offset" 441 } 442 443 var data []*model.Team 444 if _, err := s.GetReplica().Select(&data, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 445 result.Err = model.NewAppError("SqlTeamStore.GetAllPrivateTeamListing", "store.sql_team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 446 return 447 } 448 449 for _, team := range data { 450 if len(team.InviteId) == 0 { 451 team.InviteId = team.Id 452 } 453 } 454 455 result.Data = data 456 }) 457 } 458 459 func (s SqlTeamStore) GetAllTeamListing() store.StoreChannel { 460 return store.Do(func(result *store.StoreResult) { 461 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1 ORDER BY DisplayName" 462 463 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 464 query = "SELECT * FROM Teams WHERE AllowOpenInvite = true ORDER BY DisplayName" 465 } 466 467 var data []*model.Team 468 if _, err := s.GetReplica().Select(&data, query); err != nil { 469 result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 470 return 471 } 472 473 for _, team := range data { 474 if len(team.InviteId) == 0 { 475 team.InviteId = team.Id 476 } 477 } 478 479 result.Data = data 480 }) 481 } 482 483 func (s SqlTeamStore) GetAllTeamPageListing(offset int, limit int) store.StoreChannel { 484 return store.Do(func(result *store.StoreResult) { 485 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset" 486 487 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 488 query = "SELECT * FROM Teams WHERE AllowOpenInvite = true ORDER BY DisplayName LIMIT :Limit OFFSET :Offset" 489 } 490 491 var data []*model.Team 492 if _, err := s.GetReplica().Select(&data, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 493 result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 494 return 495 } 496 497 for _, team := range data { 498 if len(team.InviteId) == 0 { 499 team.InviteId = team.Id 500 } 501 } 502 503 result.Data = data 504 }) 505 } 506 507 func (s SqlTeamStore) PermanentDelete(teamId string) store.StoreChannel { 508 return store.Do(func(result *store.StoreResult) { 509 if _, err := s.GetMaster().Exec("DELETE FROM Teams WHERE Id = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil { 510 result.Err = model.NewAppError("SqlTeamStore.Delete", "store.sql_team.permanent_delete.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError) 511 return 512 } 513 }) 514 } 515 516 func (s SqlTeamStore) AnalyticsTeamCount() store.StoreChannel { 517 return store.Do(func(result *store.StoreResult) { 518 c, err := s.GetReplica().SelectInt("SELECT COUNT(*) FROM Teams WHERE DeleteAt = 0", map[string]interface{}{}) 519 if err != nil { 520 result.Err = model.NewAppError("SqlTeamStore.AnalyticsTeamCount", "store.sql_team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError) 521 return 522 } 523 result.Data = c 524 }) 525 } 526 527 var TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY = ` 528 SELECT 529 TeamMembers.*, 530 TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole, 531 TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole 532 FROM 533 TeamMembers 534 LEFT JOIN 535 Teams ON TeamMembers.TeamId = Teams.Id 536 LEFT JOIN 537 Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id 538 ` 539 540 func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) store.StoreChannel { 541 return store.Do(func(result *store.StoreResult) { 542 if result.Err = member.IsValid(); result.Err != nil { 543 return 544 } 545 546 dbMember := NewTeamMemberFromModel(member) 547 548 if maxUsersPerTeam >= 0 { 549 count, err := s.GetMaster().SelectInt( 550 `SELECT 551 COUNT(0) 552 FROM 553 TeamMembers 554 INNER JOIN 555 Users 556 ON 557 TeamMembers.UserId = Users.Id 558 WHERE 559 TeamId = :TeamId 560 AND TeamMembers.DeleteAt = 0 561 AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": member.TeamId}) 562 563 if err != nil { 564 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, "teamId="+member.TeamId+", "+err.Error(), http.StatusInternalServerError) 565 return 566 } 567 568 if count >= int64(maxUsersPerTeam) { 569 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.max_accounts.app_error", nil, "teamId="+member.TeamId, http.StatusBadRequest) 570 return 571 } 572 } 573 574 if err := s.GetMaster().Insert(dbMember); err != nil { 575 if IsUniqueConstraintError(err, []string{"TeamId", "teammembers_pkey", "PRIMARY"}) { 576 result.Err = model.NewAppError("SqlTeamStore.SaveMember", TEAM_MEMBER_EXISTS_ERROR, nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest) 577 return 578 } 579 result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.save_member.save.app_error", nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError) 580 return 581 } 582 583 var retrievedMember teamMemberWithSchemeRoles 584 if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": dbMember.TeamId, "UserId": dbMember.UserId}); err != nil { 585 if err == sql.ErrNoRows { 586 result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound) 587 return 588 } 589 result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError) 590 return 591 } 592 result.Data = retrievedMember.ToModel() 593 }) 594 } 595 596 func (s SqlTeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel { 597 return store.Do(func(result *store.StoreResult) { 598 member.PreUpdate() 599 600 if result.Err = member.IsValid(); result.Err != nil { 601 return 602 } 603 604 if _, err := s.GetMaster().Update(NewTeamMemberFromModel(member)); err != nil { 605 result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError) 606 return 607 } 608 609 var retrievedMember teamMemberWithSchemeRoles 610 if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": member.TeamId, "UserId": member.UserId}); err != nil { 611 if err == sql.ErrNoRows { 612 result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound) 613 return 614 } 615 result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError) 616 return 617 } 618 619 result.Data = retrievedMember.ToModel() 620 }) 621 } 622 623 func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel { 624 return store.Do(func(result *store.StoreResult) { 625 var dbMember teamMemberWithSchemeRoles 626 err := s.GetReplica().SelectOne(&dbMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) 627 if err != nil { 628 if err == sql.ErrNoRows { 629 result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.missing.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusNotFound) 630 return 631 } 632 result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusInternalServerError) 633 return 634 } 635 result.Data = dbMember.ToModel() 636 }) 637 } 638 639 func (s SqlTeamStore) GetMembers(teamId string, offset int, limit int) store.StoreChannel { 640 return store.Do(func(result *store.StoreResult) { 641 var dbMembers teamMemberWithSchemeRolesList 642 _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.DeleteAt = 0 LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}) 643 if err != nil { 644 result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 645 return 646 } 647 648 result.Data = dbMembers.ToModel() 649 }) 650 } 651 652 func (s SqlTeamStore) GetTotalMemberCount(teamId string) store.StoreChannel { 653 return store.Do(func(result *store.StoreResult) { 654 count, err := s.GetReplica().SelectInt(` 655 SELECT 656 count(*) 657 FROM 658 TeamMembers, 659 Users 660 WHERE 661 TeamMembers.UserId = Users.Id 662 AND TeamMembers.TeamId = :TeamId 663 AND TeamMembers.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId}) 664 if err != nil { 665 result.Err = model.NewAppError("SqlTeamStore.GetTotalMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 666 return 667 } 668 669 result.Data = count 670 }) 671 } 672 673 func (s SqlTeamStore) GetActiveMemberCount(teamId string) store.StoreChannel { 674 return store.Do(func(result *store.StoreResult) { 675 count, err := s.GetReplica().SelectInt(` 676 SELECT 677 count(*) 678 FROM 679 TeamMembers, 680 Users 681 WHERE 682 TeamMembers.UserId = Users.Id 683 AND TeamMembers.TeamId = :TeamId 684 AND TeamMembers.DeleteAt = 0 685 AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId}) 686 if err != nil { 687 result.Err = model.NewAppError("SqlTeamStore.GetActiveMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 688 return 689 } 690 691 result.Data = count 692 }) 693 } 694 695 func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string) store.StoreChannel { 696 return store.Do(func(result *store.StoreResult) { 697 var dbMembers teamMemberWithSchemeRolesList 698 props := make(map[string]interface{}) 699 idQuery := "" 700 701 for index, userId := range userIds { 702 if len(idQuery) > 0 { 703 idQuery += ", " 704 } 705 706 props["userId"+strconv.Itoa(index)] = userId 707 idQuery += ":userId" + strconv.Itoa(index) 708 } 709 710 props["TeamId"] = teamId 711 712 if _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId IN ("+idQuery+") AND TeamMembers.DeleteAt = 0", props); err != nil { 713 result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 714 return 715 } 716 result.Data = dbMembers.ToModel() 717 }) 718 } 719 720 func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel { 721 return store.Do(func(result *store.StoreResult) { 722 var dbMembers teamMemberWithSchemeRolesList 723 _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId", map[string]interface{}{"UserId": userId}) 724 if err != nil { 725 result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 726 return 727 } 728 729 result.Data = dbMembers.ToModel() 730 }) 731 } 732 733 func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage int) store.StoreChannel { 734 return store.Do(func(result *store.StoreResult) { 735 var dbMembers teamMemberWithSchemeRolesList 736 offset := page * perPage 737 _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"UserId": userId, "Limit": perPage, "Offset": offset}) 738 if err != nil { 739 result.Err = model.NewAppError("SqlTeamStore.GetTeamsForUserWithPagination", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 740 return 741 } 742 743 result.Data = dbMembers.ToModel() 744 }) 745 } 746 747 func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) store.StoreChannel { 748 return store.Do(func(result *store.StoreResult) { 749 var data []*model.ChannelUnread 750 _, err := s.GetReplica().Select(&data, 751 `SELECT 752 Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps 753 FROM 754 Channels, ChannelMembers 755 WHERE 756 Id = ChannelId 757 AND UserId = :UserId 758 AND DeleteAt = 0 759 AND TeamId != :TeamId`, 760 map[string]interface{}{"UserId": userId, "TeamId": excludeTeamId}) 761 762 if err != nil { 763 result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForAllTeams", "store.sql_team.get_unread.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 764 return 765 } 766 result.Data = data 767 }) 768 } 769 770 func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) store.StoreChannel { 771 return store.Do(func(result *store.StoreResult) { 772 var data []*model.ChannelUnread 773 _, err := s.GetReplica().Select(&data, 774 `SELECT 775 Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps 776 FROM 777 Channels, ChannelMembers 778 WHERE 779 Id = ChannelId 780 AND UserId = :UserId 781 AND TeamId = :TeamId 782 AND DeleteAt = 0`, 783 map[string]interface{}{"TeamId": teamId, "UserId": userId}) 784 785 if err != nil { 786 result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForTeam", "store.sql_team.get_unread.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 787 return 788 } 789 result.Data = data 790 }) 791 } 792 793 func (s SqlTeamStore) RemoveMember(teamId string, userId string) store.StoreChannel { 794 return store.Do(func(result *store.StoreResult) { 795 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) 796 if err != nil { 797 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 798 } 799 }) 800 } 801 802 func (s SqlTeamStore) RemoveAllMembersByTeam(teamId string) store.StoreChannel { 803 return store.Do(func(result *store.StoreResult) { 804 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}) 805 if err != nil { 806 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError) 807 } 808 }) 809 } 810 811 func (s SqlTeamStore) RemoveAllMembersByUser(userId string) store.StoreChannel { 812 return store.Do(func(result *store.StoreResult) { 813 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}) 814 if err != nil { 815 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 816 } 817 }) 818 } 819 820 func (us SqlTeamStore) UpdateLastTeamIconUpdate(teamId string, curTime int64) store.StoreChannel { 821 return store.Do(func(result *store.StoreResult) { 822 if _, err := us.GetMaster().Exec("UPDATE Teams SET LastTeamIconUpdate = :Time, UpdateAt = :Time WHERE Id = :teamId", map[string]interface{}{"Time": curTime, "teamId": teamId}); err != nil { 823 result.Err = model.NewAppError("SqlTeamStore.UpdateLastTeamIconUpdate", "store.sql_team.update_last_team_icon_update.app_error", nil, "team_id="+teamId, http.StatusInternalServerError) 824 return 825 } 826 result.Data = teamId 827 }) 828 } 829 830 func (s SqlTeamStore) GetTeamsByScheme(schemeId string, offset int, limit int) store.StoreChannel { 831 return store.Do(func(result *store.StoreResult) { 832 var teams []*model.Team 833 _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit}) 834 if err != nil { 835 result.Err = model.NewAppError("SqlTeamStore.GetTeamsByScheme", "store.sql_team.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError) 836 return 837 } 838 result.Data = teams 839 }) 840 } 841 842 // This function does the Advanced Permissions Phase 2 migration for TeamMember objects. It performs the migration 843 // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid 844 // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function 845 // *after* the new Schemes functionality has been used on an installation will have unintended consequences. 846 func (s SqlTeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) store.StoreChannel { 847 return store.Do(func(result *store.StoreResult) { 848 var transaction *gorp.Transaction 849 var err error 850 851 if transaction, err = s.GetMaster().Begin(); err != nil { 852 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 853 return 854 } 855 defer finalizeTransaction(transaction) 856 857 var teamMembers []teamMember 858 if _, err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (:FromTeamId, :FromUserId) ORDER BY TeamId, UserId LIMIT 100", map[string]interface{}{"FromTeamId": fromTeamId, "FromUserId": fromUserId}); err != nil { 859 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.select.app_error", nil, err.Error(), http.StatusInternalServerError) 860 return 861 } 862 863 if len(teamMembers) == 0 { 864 // No more team members in query result means that the migration has finished. 865 return 866 } 867 868 for _, member := range teamMembers { 869 roles := strings.Fields(member.Roles) 870 var newRoles []string 871 if !member.SchemeAdmin.Valid { 872 member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true} 873 } 874 if !member.SchemeUser.Valid { 875 member.SchemeUser = sql.NullBool{Bool: false, Valid: true} 876 } 877 for _, role := range roles { 878 if role == model.TEAM_ADMIN_ROLE_ID { 879 member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true} 880 } else if role == model.TEAM_USER_ROLE_ID { 881 member.SchemeUser = sql.NullBool{Bool: true, Valid: true} 882 } else { 883 newRoles = append(newRoles, role) 884 } 885 } 886 member.Roles = strings.Join(newRoles, " ") 887 888 if _, err := transaction.Update(&member); err != nil { 889 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.update.app_error", nil, err.Error(), http.StatusInternalServerError) 890 return 891 } 892 893 } 894 895 if err := transaction.Commit(); err != nil { 896 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 897 return 898 } 899 900 data := make(map[string]string) 901 data["TeamId"] = teamMembers[len(teamMembers)-1].TeamId 902 data["UserId"] = teamMembers[len(teamMembers)-1].UserId 903 result.Data = data 904 }) 905 } 906 907 func (s SqlTeamStore) ResetAllTeamSchemes() store.StoreChannel { 908 return store.Do(func(result *store.StoreResult) { 909 if _, err := s.GetMaster().Exec("UPDATE Teams SET SchemeId=''"); err != nil { 910 result.Err = model.NewAppError("SqlTeamStore.ResetAllTeamSchemes", "store.sql_team.reset_all_team_schemes.app_error", nil, err.Error(), http.StatusInternalServerError) 911 } 912 }) 913 } 914 915 func (s SqlTeamStore) ClearAllCustomRoleAssignments() store.StoreChannel { 916 return store.Do(func(result *store.StoreResult) { 917 builtInRoles := model.MakeDefaultRoles() 918 lastUserId := strings.Repeat("0", 26) 919 lastTeamId := strings.Repeat("0", 26) 920 921 for { 922 var transaction *gorp.Transaction 923 var err error 924 925 if transaction, err = s.GetMaster().Begin(); err != nil { 926 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 927 return 928 } 929 defer finalizeTransaction(transaction) 930 931 var teamMembers []*teamMember 932 if _, err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (:TeamId, :UserId) ORDER BY TeamId, UserId LIMIT 1000", map[string]interface{}{"TeamId": lastTeamId, "UserId": lastUserId}); err != nil { 933 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError) 934 return 935 } 936 937 if len(teamMembers) == 0 { 938 break 939 } 940 941 for _, member := range teamMembers { 942 lastUserId = member.UserId 943 lastTeamId = member.TeamId 944 945 var newRoles []string 946 947 for _, role := range strings.Fields(member.Roles) { 948 for name := range builtInRoles { 949 if name == role { 950 newRoles = append(newRoles, role) 951 break 952 } 953 } 954 } 955 956 newRolesString := strings.Join(newRoles, " ") 957 if newRolesString != member.Roles { 958 if _, err := transaction.Exec("UPDATE TeamMembers SET Roles = :Roles WHERE UserId = :UserId AND TeamId = :TeamId", map[string]interface{}{"Roles": newRolesString, "TeamId": member.TeamId, "UserId": member.UserId}); err != nil { 959 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError) 960 return 961 } 962 } 963 } 964 965 if err := transaction.Commit(); err != nil { 966 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 967 return 968 } 969 } 970 }) 971 } 972 973 func (s SqlTeamStore) AnalyticsGetTeamCountForScheme(schemeId string) store.StoreChannel { 974 return store.Do(func(result *store.StoreResult) { 975 count, err := s.GetReplica().SelectInt("SELECT count(*) FROM Teams WHERE SchemeId = :SchemeId AND DeleteAt = 0", map[string]interface{}{"SchemeId": schemeId}) 976 if err != nil { 977 result.Err = model.NewAppError("SqlTeamStore.AnalyticsGetTeamCountForScheme", "store.sql_team.analytics_get_team_count_for_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError) 978 return 979 } 980 result.Data = count 981 }) 982 } 983 984 func (s SqlTeamStore) GetAllForExportAfter(limit int, afterId string) store.StoreChannel { 985 return store.Do(func(result *store.StoreResult) { 986 var data []*model.TeamForExport 987 if _, err := s.GetReplica().Select(&data, ` 988 SELECT 989 Teams.*, 990 Schemes.Name as SchemeName 991 FROM 992 Teams 993 LEFT JOIN 994 Schemes ON Teams.SchemeId = Schemes.Id 995 WHERE 996 Teams.Id > :AfterId 997 ORDER BY 998 Id 999 LIMIT 1000 :Limit`, 1001 map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil { 1002 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 1003 return 1004 } 1005 1006 for _, team := range data { 1007 if len(team.InviteId) == 0 { 1008 team.InviteId = team.Id 1009 } 1010 } 1011 1012 result.Data = data 1013 }) 1014 } 1015 1016 func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel { 1017 return store.Do(func(result *store.StoreResult) { 1018 var members []*model.TeamMemberForExport 1019 _, err := s.GetReplica().Select(&members, ` 1020 SELECT 1021 TeamMembers.*, 1022 Teams.Name as TeamName 1023 FROM 1024 TeamMembers 1025 INNER JOIN 1026 Teams ON TeamMembers.TeamId = Teams.Id 1027 WHERE 1028 TeamMembers.UserId = :UserId 1029 AND Teams.DeleteAt = 0`, 1030 map[string]interface{}{"UserId": userId}) 1031 if err != nil { 1032 result.Err = model.NewAppError("SqlTeamStore.GetTeamMembersForExport", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 1033 return 1034 } 1035 1036 result.Data = members 1037 }) 1038 }