github.com/lologarithm/mattermost-server@v5.3.2-0.20181002060438-c82a84ed765b+incompatible/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/mattermost/mattermost-server/model" 14 "github.com/mattermost/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 team.Name = oldTeam.Name 220 221 count, err := s.GetMaster().Update(team) 222 if err != nil { 223 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.updating.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError) 224 return 225 } 226 if count != 1 { 227 result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.app_error", nil, "id="+team.Id, http.StatusInternalServerError) 228 return 229 } 230 231 result.Data = team 232 }) 233 } 234 235 func (s SqlTeamStore) UpdateDisplayName(name string, teamId string) store.StoreChannel { 236 return store.Do(func(result *store.StoreResult) { 237 if _, err := s.GetMaster().Exec("UPDATE Teams SET DisplayName = :Name WHERE Id = :Id", map[string]interface{}{"Name": name, "Id": teamId}); err != nil { 238 result.Err = model.NewAppError("SqlTeamStore.UpdateName", "store.sql_team.update_display_name.app_error", nil, "team_id="+teamId, http.StatusInternalServerError) 239 return 240 } 241 242 result.Data = teamId 243 }) 244 } 245 246 func (s SqlTeamStore) Get(id string) store.StoreChannel { 247 return store.Do(func(result *store.StoreResult) { 248 obj, err := s.GetReplica().Get(model.Team{}, id) 249 if err != nil { 250 result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.finding.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 251 return 252 } 253 if obj == nil { 254 result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.find.app_error", nil, "id="+id, http.StatusNotFound) 255 return 256 } 257 258 team := obj.(*model.Team) 259 if len(team.InviteId) == 0 { 260 team.InviteId = team.Id 261 } 262 263 result.Data = team 264 }) 265 } 266 267 func (s SqlTeamStore) GetByInviteId(inviteId string) store.StoreChannel { 268 return store.Do(func(result *store.StoreResult) { 269 team := model.Team{} 270 271 if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Id = :InviteId OR InviteId = :InviteId", map[string]interface{}{"InviteId": inviteId}); err != nil { 272 result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.finding.app_error", nil, "inviteId="+inviteId+", "+err.Error(), http.StatusNotFound) 273 return 274 } 275 276 if len(team.InviteId) == 0 { 277 team.InviteId = team.Id 278 } 279 280 if len(inviteId) == 0 || team.InviteId != inviteId { 281 result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.find.app_error", nil, "inviteId="+inviteId, http.StatusNotFound) 282 return 283 } 284 285 result.Data = &team 286 }) 287 } 288 289 func (s SqlTeamStore) GetByName(name string) store.StoreChannel { 290 return store.Do(func(result *store.StoreResult) { 291 team := model.Team{} 292 293 if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil { 294 result.Err = model.NewAppError("SqlTeamStore.GetByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError) 295 return 296 } 297 298 if len(team.InviteId) == 0 { 299 team.InviteId = team.Id 300 } 301 302 result.Data = &team 303 }) 304 } 305 306 func (s SqlTeamStore) SearchByName(name string) store.StoreChannel { 307 return store.Do(func(result *store.StoreResult) { 308 var teams []*model.Team 309 310 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Name", map[string]interface{}{"Name": name + "%"}); err != nil { 311 result.Err = model.NewAppError("SqlTeamStore.SearchByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError) 312 return 313 } 314 315 result.Data = teams 316 }) 317 } 318 319 func (s SqlTeamStore) SearchAll(term string) store.StoreChannel { 320 return store.Do(func(result *store.StoreResult) { 321 var teams []*model.Team 322 323 if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Term OR DisplayName LIKE :Term", map[string]interface{}{"Term": term + "%"}); err != nil { 324 result.Err = model.NewAppError("SqlTeamStore.SearchAll", "store.sql_team.search_all_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 325 return 326 } 327 328 result.Data = teams 329 }) 330 } 331 332 func (s SqlTeamStore) SearchOpen(term string) store.StoreChannel { 333 return store.Do(func(result *store.StoreResult) { 334 var teams []*model.Team 335 336 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 { 337 result.Err = model.NewAppError("SqlTeamStore.SearchOpen", "store.sql_team.search_open_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError) 338 return 339 } 340 341 result.Data = teams 342 }) 343 } 344 345 func (s SqlTeamStore) GetAll() store.StoreChannel { 346 return store.Do(func(result *store.StoreResult) { 347 var data []*model.Team 348 if _, err := s.GetReplica().Select(&data, "SELECT * FROM Teams"); err != nil { 349 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 350 return 351 } 352 353 for _, team := range data { 354 if len(team.InviteId) == 0 { 355 team.InviteId = team.Id 356 } 357 } 358 359 result.Data = data 360 }) 361 } 362 363 func (s SqlTeamStore) GetAllPage(offset int, limit int) store.StoreChannel { 364 return store.Do(func(result *store.StoreResult) { 365 var data []*model.Team 366 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 { 367 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 368 return 369 } 370 371 for _, team := range data { 372 if len(team.InviteId) == 0 { 373 team.InviteId = team.Id 374 } 375 } 376 377 result.Data = data 378 }) 379 } 380 381 func (s SqlTeamStore) GetTeamsByUserId(userId string) store.StoreChannel { 382 return store.Do(func(result *store.StoreResult) { 383 var data []*model.Team 384 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 { 385 result.Err = model.NewAppError("SqlTeamStore.GetTeamsByUserId", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 386 return 387 } 388 389 for _, team := range data { 390 if len(team.InviteId) == 0 { 391 team.InviteId = team.Id 392 } 393 } 394 395 result.Data = data 396 }) 397 } 398 399 func (s SqlTeamStore) GetAllTeamListing() store.StoreChannel { 400 return store.Do(func(result *store.StoreResult) { 401 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1" 402 403 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 404 query = "SELECT * FROM Teams WHERE AllowOpenInvite = true" 405 } 406 407 var data []*model.Team 408 if _, err := s.GetReplica().Select(&data, query); err != nil { 409 result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 410 return 411 } 412 413 for _, team := range data { 414 if len(team.InviteId) == 0 { 415 team.InviteId = team.Id 416 } 417 } 418 419 result.Data = data 420 }) 421 } 422 423 func (s SqlTeamStore) GetAllTeamPageListing(offset int, limit int) store.StoreChannel { 424 return store.Do(func(result *store.StoreResult) { 425 query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1 LIMIT :Limit OFFSET :Offset" 426 427 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 428 query = "SELECT * FROM Teams WHERE AllowOpenInvite = true LIMIT :Limit OFFSET :Offset" 429 } 430 431 var data []*model.Team 432 if _, err := s.GetReplica().Select(&data, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 433 result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 434 return 435 } 436 437 for _, team := range data { 438 if len(team.InviteId) == 0 { 439 team.InviteId = team.Id 440 } 441 } 442 443 result.Data = data 444 }) 445 } 446 447 func (s SqlTeamStore) PermanentDelete(teamId string) store.StoreChannel { 448 return store.Do(func(result *store.StoreResult) { 449 if _, err := s.GetMaster().Exec("DELETE FROM Teams WHERE Id = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil { 450 result.Err = model.NewAppError("SqlTeamStore.Delete", "store.sql_team.permanent_delete.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError) 451 return 452 } 453 }) 454 } 455 456 func (s SqlTeamStore) AnalyticsTeamCount() store.StoreChannel { 457 return store.Do(func(result *store.StoreResult) { 458 c, err := s.GetReplica().SelectInt("SELECT COUNT(*) FROM Teams WHERE DeleteAt = 0", map[string]interface{}{}) 459 if err != nil { 460 result.Err = model.NewAppError("SqlTeamStore.AnalyticsTeamCount", "store.sql_team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError) 461 return 462 } 463 result.Data = c 464 }) 465 } 466 467 var TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY = ` 468 SELECT 469 TeamMembers.*, 470 TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole, 471 TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole 472 FROM 473 TeamMembers 474 LEFT JOIN 475 Teams ON TeamMembers.TeamId = Teams.Id 476 LEFT JOIN 477 Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id 478 ` 479 480 func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) store.StoreChannel { 481 return store.Do(func(result *store.StoreResult) { 482 if result.Err = member.IsValid(); result.Err != nil { 483 return 484 } 485 486 dbMember := NewTeamMemberFromModel(member) 487 488 if maxUsersPerTeam >= 0 { 489 count, err := s.GetMaster().SelectInt( 490 `SELECT 491 COUNT(0) 492 FROM 493 TeamMembers 494 INNER JOIN 495 Users 496 ON 497 TeamMembers.UserId = Users.Id 498 WHERE 499 TeamId = :TeamId 500 AND TeamMembers.DeleteAt = 0 501 AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": member.TeamId}) 502 503 if err != nil { 504 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, "teamId="+member.TeamId+", "+err.Error(), http.StatusInternalServerError) 505 return 506 } 507 508 if count >= int64(maxUsersPerTeam) { 509 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.max_accounts.app_error", nil, "teamId="+member.TeamId, http.StatusBadRequest) 510 return 511 } 512 } 513 514 if err := s.GetMaster().Insert(dbMember); err != nil { 515 if IsUniqueConstraintError(err, []string{"TeamId", "teammembers_pkey", "PRIMARY"}) { 516 result.Err = model.NewAppError("SqlTeamStore.SaveMember", TEAM_MEMBER_EXISTS_ERROR, nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest) 517 return 518 } 519 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) 520 return 521 } 522 523 var retrievedMember teamMemberWithSchemeRoles 524 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 { 525 if err == sql.ErrNoRows { 526 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) 527 return 528 } 529 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) 530 return 531 } 532 result.Data = retrievedMember.ToModel() 533 }) 534 } 535 536 func (s SqlTeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel { 537 return store.Do(func(result *store.StoreResult) { 538 member.PreUpdate() 539 540 if result.Err = member.IsValid(); result.Err != nil { 541 return 542 } 543 544 if _, err := s.GetMaster().Update(NewTeamMemberFromModel(member)); err != nil { 545 result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError) 546 return 547 } 548 549 var retrievedMember teamMemberWithSchemeRoles 550 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 { 551 if err == sql.ErrNoRows { 552 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) 553 return 554 } 555 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) 556 return 557 } 558 559 result.Data = retrievedMember.ToModel() 560 }) 561 } 562 563 func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel { 564 return store.Do(func(result *store.StoreResult) { 565 var dbMember teamMemberWithSchemeRoles 566 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}) 567 if err != nil { 568 if err == sql.ErrNoRows { 569 result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.missing.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusNotFound) 570 return 571 } 572 result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusInternalServerError) 573 return 574 } 575 result.Data = dbMember.ToModel() 576 }) 577 } 578 579 func (s SqlTeamStore) GetMembers(teamId string, offset int, limit int) store.StoreChannel { 580 return store.Do(func(result *store.StoreResult) { 581 var dbMembers teamMemberWithSchemeRolesList 582 _, 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}) 583 if err != nil { 584 result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 585 return 586 } 587 588 result.Data = dbMembers.ToModel() 589 }) 590 } 591 592 func (s SqlTeamStore) GetTotalMemberCount(teamId string) store.StoreChannel { 593 return store.Do(func(result *store.StoreResult) { 594 count, err := s.GetReplica().SelectInt(` 595 SELECT 596 count(*) 597 FROM 598 TeamMembers, 599 Users 600 WHERE 601 TeamMembers.UserId = Users.Id 602 AND TeamMembers.TeamId = :TeamId 603 AND TeamMembers.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId}) 604 if err != nil { 605 result.Err = model.NewAppError("SqlTeamStore.GetTotalMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 606 return 607 } 608 609 result.Data = count 610 }) 611 } 612 613 func (s SqlTeamStore) GetActiveMemberCount(teamId string) store.StoreChannel { 614 return store.Do(func(result *store.StoreResult) { 615 count, err := s.GetReplica().SelectInt(` 616 SELECT 617 count(*) 618 FROM 619 TeamMembers, 620 Users 621 WHERE 622 TeamMembers.UserId = Users.Id 623 AND TeamMembers.TeamId = :TeamId 624 AND TeamMembers.DeleteAt = 0 625 AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId}) 626 if err != nil { 627 result.Err = model.NewAppError("SqlTeamStore.GetActiveMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 628 return 629 } 630 631 result.Data = count 632 }) 633 } 634 635 func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string) store.StoreChannel { 636 return store.Do(func(result *store.StoreResult) { 637 var dbMembers teamMemberWithSchemeRolesList 638 props := make(map[string]interface{}) 639 idQuery := "" 640 641 for index, userId := range userIds { 642 if len(idQuery) > 0 { 643 idQuery += ", " 644 } 645 646 props["userId"+strconv.Itoa(index)] = userId 647 idQuery += ":userId" + strconv.Itoa(index) 648 } 649 650 props["TeamId"] = teamId 651 652 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 { 653 result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 654 return 655 } 656 result.Data = dbMembers.ToModel() 657 }) 658 } 659 660 func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel { 661 return store.Do(func(result *store.StoreResult) { 662 var dbMembers teamMemberWithSchemeRolesList 663 _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId", map[string]interface{}{"UserId": userId}) 664 if err != nil { 665 result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 666 return 667 } 668 669 result.Data = dbMembers.ToModel() 670 }) 671 } 672 673 func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) store.StoreChannel { 674 return store.Do(func(result *store.StoreResult) { 675 var data []*model.ChannelUnread 676 _, err := s.GetReplica().Select(&data, 677 `SELECT 678 Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps 679 FROM 680 Channels, ChannelMembers 681 WHERE 682 Id = ChannelId 683 AND UserId = :UserId 684 AND DeleteAt = 0 685 AND TeamId != :TeamId`, 686 map[string]interface{}{"UserId": userId, "TeamId": excludeTeamId}) 687 688 if err != nil { 689 result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForAllTeams", "store.sql_team.get_unread.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 690 return 691 } 692 result.Data = data 693 }) 694 } 695 696 func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) store.StoreChannel { 697 return store.Do(func(result *store.StoreResult) { 698 var data []*model.ChannelUnread 699 _, err := s.GetReplica().Select(&data, 700 `SELECT 701 Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps 702 FROM 703 Channels, ChannelMembers 704 WHERE 705 Id = ChannelId 706 AND UserId = :UserId 707 AND TeamId = :TeamId 708 AND DeleteAt = 0`, 709 map[string]interface{}{"TeamId": teamId, "UserId": userId}) 710 711 if err != nil { 712 result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForTeam", "store.sql_team.get_unread.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError) 713 return 714 } 715 result.Data = data 716 }) 717 } 718 719 func (s SqlTeamStore) RemoveMember(teamId string, userId string) store.StoreChannel { 720 return store.Do(func(result *store.StoreResult) { 721 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) 722 if err != nil { 723 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 724 } 725 }) 726 } 727 728 func (s SqlTeamStore) RemoveAllMembersByTeam(teamId string) store.StoreChannel { 729 return store.Do(func(result *store.StoreResult) { 730 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}) 731 if err != nil { 732 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError) 733 } 734 }) 735 } 736 737 func (s SqlTeamStore) RemoveAllMembersByUser(userId string) store.StoreChannel { 738 return store.Do(func(result *store.StoreResult) { 739 _, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}) 740 if err != nil { 741 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 742 } 743 }) 744 } 745 746 func (us SqlTeamStore) UpdateLastTeamIconUpdate(teamId string, curTime int64) store.StoreChannel { 747 return store.Do(func(result *store.StoreResult) { 748 if _, err := us.GetMaster().Exec("UPDATE Teams SET LastTeamIconUpdate = :Time, UpdateAt = :Time WHERE Id = :teamId", map[string]interface{}{"Time": curTime, "teamId": teamId}); err != nil { 749 result.Err = model.NewAppError("SqlTeamStore.UpdateLastTeamIconUpdate", "store.sql_team.update_last_team_icon_update.app_error", nil, "team_id="+teamId, http.StatusInternalServerError) 750 return 751 } 752 result.Data = teamId 753 }) 754 } 755 756 func (s SqlTeamStore) GetTeamsByScheme(schemeId string, offset int, limit int) store.StoreChannel { 757 return store.Do(func(result *store.StoreResult) { 758 var teams []*model.Team 759 _, 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}) 760 if err != nil { 761 result.Err = model.NewAppError("SqlTeamStore.GetTeamsByScheme", "store.sql_team.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError) 762 return 763 } 764 result.Data = teams 765 }) 766 } 767 768 // This function does the Advanced Permissions Phase 2 migration for TeamMember objects. It performs the migration 769 // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid 770 // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function 771 // *after* the new Schemes functionality has been used on an installation will have unintended consequences. 772 func (s SqlTeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) store.StoreChannel { 773 return store.Do(func(result *store.StoreResult) { 774 var transaction *gorp.Transaction 775 var err error 776 777 if transaction, err = s.GetMaster().Begin(); err != nil { 778 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 779 return 780 } 781 782 var teamMembers []teamMember 783 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 { 784 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.select.app_error", nil, err.Error(), http.StatusInternalServerError) 785 return 786 } 787 788 if len(teamMembers) == 0 { 789 // No more team members in query result means that the migration has finished. 790 return 791 } 792 793 for _, member := range teamMembers { 794 roles := strings.Fields(member.Roles) 795 var newRoles []string 796 if !member.SchemeAdmin.Valid { 797 member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true} 798 } 799 if !member.SchemeUser.Valid { 800 member.SchemeUser = sql.NullBool{Bool: false, Valid: true} 801 } 802 for _, role := range roles { 803 if role == model.TEAM_ADMIN_ROLE_ID { 804 member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true} 805 } else if role == model.TEAM_USER_ROLE_ID { 806 member.SchemeUser = sql.NullBool{Bool: true, Valid: true} 807 } else { 808 newRoles = append(newRoles, role) 809 } 810 } 811 member.Roles = strings.Join(newRoles, " ") 812 813 if _, err := transaction.Update(&member); err != nil { 814 if err2 := transaction.Rollback(); err2 != nil { 815 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 816 return 817 } 818 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.update.app_error", nil, err.Error(), http.StatusInternalServerError) 819 return 820 } 821 822 } 823 824 if err := transaction.Commit(); err != nil { 825 if err2 := transaction.Rollback(); err2 != nil { 826 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 827 return 828 } 829 result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 830 return 831 } 832 833 data := make(map[string]string) 834 data["TeamId"] = teamMembers[len(teamMembers)-1].TeamId 835 data["UserId"] = teamMembers[len(teamMembers)-1].UserId 836 result.Data = data 837 }) 838 } 839 840 func (s SqlTeamStore) ResetAllTeamSchemes() store.StoreChannel { 841 return store.Do(func(result *store.StoreResult) { 842 if _, err := s.GetMaster().Exec("UPDATE Teams SET SchemeId=''"); err != nil { 843 result.Err = model.NewAppError("SqlTeamStore.ResetAllTeamSchemes", "store.sql_team.reset_all_team_schemes.app_error", nil, err.Error(), http.StatusInternalServerError) 844 } 845 }) 846 } 847 848 func (s SqlTeamStore) ClearAllCustomRoleAssignments() store.StoreChannel { 849 return store.Do(func(result *store.StoreResult) { 850 builtInRoles := model.MakeDefaultRoles() 851 lastUserId := strings.Repeat("0", 26) 852 lastTeamId := strings.Repeat("0", 26) 853 854 for { 855 var transaction *gorp.Transaction 856 var err error 857 858 if transaction, err = s.GetMaster().Begin(); err != nil { 859 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 860 return 861 } 862 863 var teamMembers []*teamMember 864 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 { 865 if err2 := transaction.Rollback(); err2 != nil { 866 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 867 return 868 } 869 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError) 870 return 871 } 872 873 if len(teamMembers) == 0 { 874 break 875 } 876 877 for _, member := range teamMembers { 878 lastUserId = member.UserId 879 lastTeamId = member.TeamId 880 881 var newRoles []string 882 883 for _, role := range strings.Fields(member.Roles) { 884 for name := range builtInRoles { 885 if name == role { 886 newRoles = append(newRoles, role) 887 break 888 } 889 } 890 } 891 892 newRolesString := strings.Join(newRoles, " ") 893 if newRolesString != member.Roles { 894 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 { 895 if err2 := transaction.Rollback(); err2 != nil { 896 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 897 return 898 } 899 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError) 900 return 901 } 902 } 903 } 904 905 if err := transaction.Commit(); err != nil { 906 if err2 := transaction.Rollback(); err2 != nil { 907 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 908 return 909 } 910 result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 911 return 912 } 913 } 914 }) 915 } 916 917 func (s SqlTeamStore) AnalyticsGetTeamCountForScheme(schemeId string) store.StoreChannel { 918 return store.Do(func(result *store.StoreResult) { 919 count, err := s.GetReplica().SelectInt("SELECT count(*) FROM Teams WHERE SchemeId = :SchemeId AND DeleteAt = 0", map[string]interface{}{"SchemeId": schemeId}) 920 if err != nil { 921 result.Err = model.NewAppError("SqlTeamStore.AnalyticsGetTeamCountForScheme", "store.sql_team.analytics_get_team_count_for_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError) 922 return 923 } 924 result.Data = count 925 }) 926 } 927 928 func (s SqlTeamStore) GetAllForExportAfter(limit int, afterId string) store.StoreChannel { 929 return store.Do(func(result *store.StoreResult) { 930 var data []*model.TeamForExport 931 if _, err := s.GetReplica().Select(&data, ` 932 SELECT 933 Teams.*, 934 Schemes.Name as SchemeName 935 FROM 936 Teams 937 LEFT JOIN 938 Schemes ON Teams.SchemeId = Schemes.Id 939 WHERE 940 Teams.Id > :AfterId 941 ORDER BY 942 Id 943 LIMIT 944 :Limit`, 945 map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil { 946 result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 947 return 948 } 949 950 for _, team := range data { 951 if len(team.InviteId) == 0 { 952 team.InviteId = team.Id 953 } 954 } 955 956 result.Data = data 957 }) 958 } 959 960 func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel { 961 return store.Do(func(result *store.StoreResult) { 962 var members []*model.TeamMemberForExport 963 _, err := s.GetReplica().Select(&members, ` 964 SELECT 965 TeamMembers.*, 966 Teams.Name as TeamName 967 FROM 968 TeamMembers 969 INNER JOIN 970 Teams ON TeamMembers.TeamId = Teams.Id 971 WHERE 972 TeamMembers.UserId = :UserId 973 AND Teams.DeleteAt = 0`, 974 map[string]interface{}{"UserId": userId}) 975 if err != nil { 976 result.Err = model.NewAppError("SqlTeamStore.GetTeamMembersForExport", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError) 977 return 978 } 979 980 result.Data = members 981 }) 982 }