github.com/adacta-ru/mattermost-server/v6@v6.0.0/app/team.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "bytes" 8 "context" 9 "errors" 10 "fmt" 11 "image" 12 "image/png" 13 "io" 14 "mime/multipart" 15 "net/http" 16 "net/url" 17 "strings" 18 19 "github.com/disintegration/imaging" 20 "github.com/adacta-ru/mattermost-server/v6/mlog" 21 "github.com/adacta-ru/mattermost-server/v6/model" 22 "github.com/adacta-ru/mattermost-server/v6/plugin" 23 "github.com/adacta-ru/mattermost-server/v6/store" 24 "github.com/adacta-ru/mattermost-server/v6/utils" 25 ) 26 27 func (a *App) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { 28 team.InviteId = "" 29 rteam, err := a.Srv().Store.Team().Save(team) 30 if err != nil { 31 var invErr *store.ErrInvalidInput 32 var appErr *model.AppError 33 switch { 34 case errors.As(err, &invErr): 35 return nil, model.NewAppError("CreateTeam", "app.team.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest) 36 case errors.As(err, &appErr): 37 return nil, appErr 38 default: 39 return nil, model.NewAppError("CreateTeam", "app.team.save.app_error", nil, err.Error(), http.StatusInternalServerError) 40 } 41 } 42 43 if _, err := a.CreateDefaultChannels(rteam.Id); err != nil { 44 return nil, err 45 } 46 47 return rteam, nil 48 } 49 50 func (a *App) CreateTeamWithUser(team *model.Team, userId string) (*model.Team, *model.AppError) { 51 user, err := a.GetUser(userId) 52 if err != nil { 53 return nil, err 54 } 55 team.Email = user.Email 56 57 if !a.isTeamEmailAllowed(user, team) { 58 return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest) 59 } 60 61 rteam, err := a.CreateTeam(team) 62 if err != nil { 63 return nil, err 64 } 65 66 if err = a.JoinUserToTeam(rteam, user, ""); err != nil { 67 return nil, err 68 } 69 70 return rteam, nil 71 } 72 73 func (a *App) normalizeDomains(domains string) []string { 74 // commas and @ signs are optional 75 // can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org 76 return strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(domains, "@", " ", -1), ",", " ", -1)))) 77 } 78 79 func (a *App) isEmailAddressAllowed(email string, allowedDomains []string) bool { 80 for _, restriction := range allowedDomains { 81 domains := a.normalizeDomains(restriction) 82 if len(domains) <= 0 { 83 continue 84 } 85 matched := false 86 for _, d := range domains { 87 if strings.HasSuffix(email, "@"+d) { 88 matched = true 89 break 90 } 91 } 92 if !matched { 93 return false 94 } 95 } 96 97 return true 98 } 99 100 func (a *App) isTeamEmailAllowed(user *model.User, team *model.Team) bool { 101 if user.IsBot { 102 return true 103 } 104 email := strings.ToLower(user.Email) 105 allowedDomains := a.getAllowedDomains(user, team) 106 return a.isEmailAddressAllowed(email, allowedDomains) 107 } 108 109 func (a *App) getAllowedDomains(user *model.User, team *model.Team) []string { 110 if user.IsGuest() { 111 return []string{*a.Config().GuestAccountsSettings.RestrictCreationToDomains} 112 } 113 // First check per team allowedDomains, then app wide restrictions 114 return []string{team.AllowedDomains, *a.Config().TeamSettings.RestrictCreationToDomains} 115 } 116 117 func (a *App) CheckValidDomains(team *model.Team) *model.AppError { 118 validDomains := a.normalizeDomains(*a.Config().TeamSettings.RestrictCreationToDomains) 119 if len(validDomains) > 0 { 120 for _, domain := range a.normalizeDomains(team.AllowedDomains) { 121 matched := false 122 for _, d := range validDomains { 123 if domain == d { 124 matched = true 125 break 126 } 127 } 128 if !matched { 129 err := model.NewAppError("UpdateTeam", "api.team.update_restricted_domains.mismatch.app_error", map[string]interface{}{"Domain": domain}, "", http.StatusBadRequest) 130 return err 131 } 132 } 133 } 134 135 return nil 136 } 137 138 func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) { 139 oldTeam, err := a.GetTeam(team.Id) 140 if err != nil { 141 return nil, err 142 } 143 144 if err = a.CheckValidDomains(team); err != nil { 145 return nil, err 146 } 147 148 oldTeam.DisplayName = team.DisplayName 149 oldTeam.Description = team.Description 150 oldTeam.AllowOpenInvite = team.AllowOpenInvite 151 oldTeam.CompanyName = team.CompanyName 152 oldTeam.AllowedDomains = team.AllowedDomains 153 oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate 154 oldTeam.GroupConstrained = team.GroupConstrained 155 156 oldTeam, err = a.updateTeamUnsanitized(oldTeam) 157 if err != nil { 158 return team, err 159 } 160 161 a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM) 162 163 return oldTeam, nil 164 } 165 166 func (a *App) updateTeamUnsanitized(team *model.Team) (*model.Team, *model.AppError) { 167 team, err := a.Srv().Store.Team().Update(team) 168 if err != nil { 169 var invErr *store.ErrInvalidInput 170 var appErr *model.AppError 171 switch { 172 case errors.As(err, &invErr): 173 return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 174 case errors.As(err, &appErr): 175 return nil, appErr 176 default: 177 return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError) 178 } 179 } 180 181 return team, nil 182 } 183 184 // RenameTeam is used to rename the team Name and the DisplayName fields 185 func (a *App) RenameTeam(team *model.Team, newTeamName string, newDisplayName string) (*model.Team, *model.AppError) { 186 187 // check if name is occupied 188 _, errnf := a.GetTeamByName(newTeamName) 189 190 // "-" can be used as a newTeamName if only DisplayName change is wanted 191 if errnf == nil && newTeamName != "-" { 192 errbody := fmt.Sprintf("team with name %s already exists", newTeamName) 193 return nil, model.NewAppError("RenameTeam", "app.team.rename_team.name_occupied", nil, errbody, http.StatusBadRequest) 194 } 195 196 if newTeamName != "-" { 197 team.Name = newTeamName 198 } 199 200 if newDisplayName != "" { 201 team.DisplayName = newDisplayName 202 } 203 204 newTeam, err := a.updateTeamUnsanitized(team) 205 if err != nil { 206 return nil, err 207 } 208 209 return newTeam, nil 210 } 211 212 func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError) { 213 oldTeam, err := a.GetTeam(team.Id) 214 if err != nil { 215 return nil, err 216 } 217 218 oldTeam.SchemeId = team.SchemeId 219 220 oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam) 221 if nErr != nil { 222 var invErr *store.ErrInvalidInput 223 var appErr *model.AppError 224 switch { 225 case errors.As(nErr, &invErr): 226 return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 227 case errors.As(nErr, &appErr): 228 return nil, appErr 229 default: 230 return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError) 231 } 232 } 233 234 a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM_SCHEME) 235 236 return oldTeam, nil 237 } 238 239 func (a *App) UpdateTeamPrivacy(teamId string, teamType string, allowOpenInvite bool) *model.AppError { 240 oldTeam, err := a.GetTeam(teamId) 241 if err != nil { 242 return err 243 } 244 245 // Force a regeneration of the invite token if changing a team to restricted. 246 if (allowOpenInvite != oldTeam.AllowOpenInvite || teamType != oldTeam.Type) && (!allowOpenInvite || teamType == model.TEAM_INVITE) { 247 oldTeam.InviteId = model.NewId() 248 } 249 250 oldTeam.Type = teamType 251 oldTeam.AllowOpenInvite = allowOpenInvite 252 253 oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam) 254 if nErr != nil { 255 var invErr *store.ErrInvalidInput 256 var appErr *model.AppError 257 switch { 258 case errors.As(nErr, &invErr): 259 return model.NewAppError("UpdateTeamPrivacy", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 260 case errors.As(nErr, &appErr): 261 return appErr 262 default: 263 return model.NewAppError("UpdateTeamPrivacy", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError) 264 } 265 } 266 267 a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM) 268 269 return nil 270 } 271 272 func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *model.AppError) { 273 team, err := a.GetTeam(teamId) 274 if err != nil { 275 return nil, err 276 } 277 278 team.Patch(patch) 279 if patch.AllowOpenInvite != nil && !*patch.AllowOpenInvite { 280 team.InviteId = model.NewId() 281 } 282 283 if err = a.CheckValidDomains(team); err != nil { 284 return nil, err 285 } 286 287 team, err = a.updateTeamUnsanitized(team) 288 if err != nil { 289 return team, err 290 } 291 292 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM) 293 294 return team, nil 295 } 296 297 func (a *App) RegenerateTeamInviteId(teamId string) (*model.Team, *model.AppError) { 298 team, err := a.GetTeam(teamId) 299 if err != nil { 300 return nil, err 301 } 302 303 team.InviteId = model.NewId() 304 305 updatedTeam, nErr := a.Srv().Store.Team().Update(team) 306 if nErr != nil { 307 var invErr *store.ErrInvalidInput 308 var appErr *model.AppError 309 switch { 310 case errors.As(nErr, &invErr): 311 return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 312 case errors.As(nErr, &appErr): 313 return nil, appErr 314 default: 315 return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError) 316 } 317 } 318 319 a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM) 320 321 return updatedTeam, nil 322 } 323 324 func (a *App) sendTeamEvent(team *model.Team, event string) { 325 sanitizedTeam := &model.Team{} 326 *sanitizedTeam = *team 327 sanitizedTeam.Sanitize() 328 329 teamId := "" // no filtering by teamId by default 330 if event == model.WEBSOCKET_EVENT_UPDATE_TEAM { 331 // in case of update_team event - we send the message only to members of that team 332 teamId = team.Id 333 } 334 message := model.NewWebSocketEvent(event, teamId, "", "", nil) 335 message.Add("team", sanitizedTeam.ToJson()) 336 a.Publish(message) 337 } 338 339 func (a *App) GetSchemeRolesForTeam(teamId string) (string, string, string, *model.AppError) { 340 team, err := a.GetTeam(teamId) 341 if err != nil { 342 return "", "", "", err 343 } 344 345 if team.SchemeId != nil && *team.SchemeId != "" { 346 scheme, err := a.GetScheme(*team.SchemeId) 347 if err != nil { 348 return "", "", "", err 349 } 350 return scheme.DefaultTeamGuestRole, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil 351 } 352 353 return model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID, nil 354 } 355 356 func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) { 357 member, nErr := a.Srv().Store.Team().GetMember(teamId, userId) 358 if nErr != nil { 359 var nfErr *store.ErrNotFound 360 switch { 361 case errors.As(nErr, &nfErr): 362 return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 363 default: 364 return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) 365 } 366 } 367 368 if member == nil { 369 return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId, http.StatusBadRequest) 370 } 371 372 schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamId) 373 if err != nil { 374 return nil, err 375 } 376 377 prevSchemeGuestValue := member.SchemeGuest 378 379 var newExplicitRoles []string 380 member.SchemeGuest = false 381 member.SchemeUser = false 382 member.SchemeAdmin = false 383 384 for _, roleName := range strings.Fields(newRoles) { 385 var role *model.Role 386 role, err = a.GetRoleByName(roleName) 387 if err != nil { 388 err.StatusCode = http.StatusBadRequest 389 return nil, err 390 } 391 if !role.SchemeManaged { 392 // The role is not scheme-managed, so it's OK to apply it to the explicit roles field. 393 newExplicitRoles = append(newExplicitRoles, roleName) 394 } else { 395 // The role is scheme-managed, so need to check if it is part of the scheme for this channel or not. 396 switch roleName { 397 case schemeAdminRole: 398 member.SchemeAdmin = true 399 case schemeUserRole: 400 member.SchemeUser = true 401 case schemeGuestRole: 402 member.SchemeGuest = true 403 default: 404 // If not part of the scheme for this team, then it is not allowed to apply it as an explicit role. 405 return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest) 406 } 407 } 408 } 409 410 if member.SchemeGuest && member.SchemeUser { 411 return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) 412 } 413 414 if prevSchemeGuestValue != member.SchemeGuest { 415 return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest) 416 } 417 418 member.ExplicitRoles = strings.Join(newExplicitRoles, " ") 419 420 member, nErr = a.Srv().Store.Team().UpdateMember(member) 421 if nErr != nil { 422 var appErr *model.AppError 423 switch { 424 case errors.As(nErr, &appErr): 425 return nil, appErr 426 default: 427 return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 428 } 429 } 430 431 a.ClearSessionCacheForUser(userId) 432 433 a.sendUpdatedMemberRoleEvent(userId, member) 434 435 return member, nil 436 } 437 438 func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) { 439 member, err := a.GetTeamMember(teamId, userId) 440 if err != nil { 441 return nil, err 442 } 443 444 member.SchemeAdmin = isSchemeAdmin 445 member.SchemeUser = isSchemeUser 446 member.SchemeGuest = isSchemeGuest 447 448 if member.SchemeUser && member.SchemeGuest { 449 return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) 450 } 451 452 // If the migration is not completed, we also need to check the default team_admin/team_user roles are not present in the roles field. 453 if err = a.IsPhase2MigrationCompleted(); err != nil { 454 member.ExplicitRoles = RemoveRoles([]string{model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID}, member.ExplicitRoles) 455 } 456 457 member, nErr := a.Srv().Store.Team().UpdateMember(member) 458 if nErr != nil { 459 var appErr *model.AppError 460 switch { 461 case errors.As(nErr, &appErr): 462 return nil, appErr 463 default: 464 return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 465 } 466 } 467 468 a.ClearSessionCacheForUser(userId) 469 470 a.sendUpdatedMemberRoleEvent(userId, member) 471 472 return member, nil 473 } 474 475 func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) { 476 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil) 477 message.Add("member", member.ToJson()) 478 a.Publish(message) 479 } 480 481 func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) { 482 tchan := make(chan store.StoreResult, 1) 483 go func() { 484 team, err := a.Srv().Store.Team().Get(teamId) 485 tchan <- store.StoreResult{Data: team, NErr: err} 486 close(tchan) 487 }() 488 489 uchan := make(chan store.StoreResult, 1) 490 go func() { 491 user, err := a.Srv().Store.User().Get(userId) 492 uchan <- store.StoreResult{Data: user, NErr: err} 493 close(uchan) 494 }() 495 496 result := <-tchan 497 if result.NErr != nil { 498 var nfErr *store.ErrNotFound 499 switch { 500 case errors.As(result.NErr, &nfErr): 501 return nil, model.NewAppError("AddUserToTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 502 default: 503 return nil, model.NewAppError("AddUserToTeam", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 504 } 505 } 506 team := result.Data.(*model.Team) 507 508 result = <-uchan 509 if result.NErr != nil { 510 var nfErr *store.ErrNotFound 511 switch { 512 case errors.As(result.NErr, &nfErr): 513 return nil, model.NewAppError("AddUserToTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 514 default: 515 return nil, model.NewAppError("AddUserToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 516 } 517 } 518 user := result.Data.(*model.User) 519 520 if err := a.JoinUserToTeam(team, user, userRequestorId); err != nil { 521 return nil, err 522 } 523 524 return team, nil 525 } 526 527 func (a *App) AddUserToTeamByTeamId(teamId string, user *model.User) *model.AppError { 528 team, err := a.Srv().Store.Team().Get(teamId) 529 if err != nil { 530 var nfErr *store.ErrNotFound 531 switch { 532 case errors.As(err, &nfErr): 533 return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 534 default: 535 return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 536 } 537 } 538 539 return a.JoinUserToTeam(team, user, "") 540 } 541 542 func (a *App) AddUserToTeamByToken(userId string, tokenId string) (*model.Team, *model.AppError) { 543 token, err := a.Srv().Store.Token().GetByToken(tokenId) 544 if err != nil { 545 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, err.Error(), http.StatusBadRequest) 546 } 547 548 if token.Type != TOKEN_TYPE_TEAM_INVITATION && token.Type != TOKEN_TYPE_GUEST_INVITATION { 549 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest) 550 } 551 552 if model.GetMillis()-token.CreateAt >= INVITATION_EXPIRY_TIME { 553 a.DeleteToken(token) 554 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest) 555 } 556 557 tokenData := model.MapFromJson(strings.NewReader(token.Extra)) 558 559 tchan := make(chan store.StoreResult, 1) 560 go func() { 561 team, err := a.Srv().Store.Team().Get(tokenData["teamId"]) 562 tchan <- store.StoreResult{Data: team, NErr: err} 563 close(tchan) 564 }() 565 566 uchan := make(chan store.StoreResult, 1) 567 go func() { 568 user, err := a.Srv().Store.User().Get(userId) 569 uchan <- store.StoreResult{Data: user, NErr: err} 570 close(uchan) 571 }() 572 573 result := <-tchan 574 if result.NErr != nil { 575 var nfErr *store.ErrNotFound 576 switch { 577 case errors.As(result.NErr, &nfErr): 578 return nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 579 default: 580 return nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 581 } 582 } 583 team := result.Data.(*model.Team) 584 585 if team.IsGroupConstrained() { 586 return nil, model.NewAppError("AddUserToTeamByToken", "app.team.invite_token.group_constrained.error", nil, "", http.StatusForbidden) 587 } 588 589 result = <-uchan 590 if result.NErr != nil { 591 var nfErr *store.ErrNotFound 592 switch { 593 case errors.As(result.NErr, &nfErr): 594 return nil, model.NewAppError("AddUserToTeamByToken", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 595 default: 596 return nil, model.NewAppError("AddUserToTeamByToken", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 597 } 598 } 599 user := result.Data.(*model.User) 600 601 if user.IsGuest() && token.Type == TOKEN_TYPE_TEAM_INVITATION { 602 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest) 603 } 604 if !user.IsGuest() && token.Type == TOKEN_TYPE_GUEST_INVITATION { 605 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest) 606 } 607 608 if err := a.JoinUserToTeam(team, user, ""); err != nil { 609 return nil, err 610 } 611 612 if token.Type == TOKEN_TYPE_GUEST_INVITATION { 613 channels, err := a.Srv().Store.Channel().GetChannelsByIds(strings.Split(tokenData["channels"], " "), false) 614 if err != nil { 615 return nil, model.NewAppError("AddUserToTeamByToken", "app.channel.get_channels_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError) 616 } 617 618 for _, channel := range channels { 619 _, err := a.AddUserToChannel(user, channel) 620 if err != nil { 621 mlog.Error("error adding user to channel", mlog.Err(err)) 622 } 623 } 624 } 625 626 if err := a.DeleteToken(token); err != nil { 627 return nil, err 628 } 629 630 return team, nil 631 } 632 633 func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) { 634 tchan := make(chan store.StoreResult, 1) 635 go func() { 636 team, err := a.Srv().Store.Team().GetByInviteId(inviteId) 637 tchan <- store.StoreResult{Data: team, NErr: err} 638 close(tchan) 639 }() 640 641 uchan := make(chan store.StoreResult, 1) 642 go func() { 643 user, err := a.Srv().Store.User().Get(userId) 644 uchan <- store.StoreResult{Data: user, NErr: err} 645 close(uchan) 646 }() 647 648 result := <-tchan 649 if result.NErr != nil { 650 var nfErr *store.ErrNotFound 651 switch { 652 case errors.As(result.NErr, &nfErr): 653 return nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 654 default: 655 return nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 656 } 657 } 658 team := result.Data.(*model.Team) 659 660 result = <-uchan 661 if result.NErr != nil { 662 var nfErr *store.ErrNotFound 663 switch { 664 case errors.As(result.NErr, &nfErr): 665 return nil, model.NewAppError("AddUserToTeamByInviteId", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 666 default: 667 return nil, model.NewAppError("AddUserToTeamByInviteId", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 668 } 669 } 670 user := result.Data.(*model.User) 671 672 if err := a.JoinUserToTeam(team, user, ""); err != nil { 673 return nil, err 674 } 675 676 return team, nil 677 } 678 679 // Returns three values: 680 // 1. a pointer to the team member, if successful 681 // 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false. 682 // 3. a pointer to an AppError if something went wrong. 683 func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) { 684 tm := &model.TeamMember{ 685 TeamId: team.Id, 686 UserId: user.Id, 687 SchemeGuest: user.IsGuest(), 688 SchemeUser: !user.IsGuest(), 689 } 690 691 if !user.IsGuest() { 692 userShouldBeAdmin, err := a.UserIsInAdminRoleGroup(user.Id, team.Id, model.GroupSyncableTypeTeam) 693 if err != nil { 694 return nil, false, err 695 } 696 tm.SchemeAdmin = userShouldBeAdmin 697 } 698 699 if team.Email == user.Email { 700 tm.SchemeAdmin = true 701 } 702 703 rtm, err := a.Srv().Store.Team().GetMember(team.Id, user.Id) 704 if err != nil { 705 // Membership appears to be missing. Lets try to add. 706 tmr, nErr := a.Srv().Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam) 707 if nErr != nil { 708 var appErr *model.AppError 709 var conflictErr *store.ErrConflict 710 var limitExeededErr *store.ErrLimitExceeded 711 switch { 712 case errors.As(nErr, &appErr): // in case we haven't converted to plain error. 713 return nil, false, appErr 714 case errors.As(nErr, &conflictErr): 715 return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.conflict.app_error", nil, nErr.Error(), http.StatusBadRequest) 716 case errors.As(nErr, &limitExeededErr): 717 return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.max_accounts.app_error", nil, nErr.Error(), http.StatusBadRequest) 718 default: // last fallback in case it doesn't map to an existing app error. 719 return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) 720 } 721 } 722 return tmr, false, nil 723 } 724 725 // Membership already exists. Check if deleted and update, otherwise do nothing 726 // Do nothing if already added 727 if rtm.DeleteAt == 0 { 728 return rtm, true, nil 729 } 730 731 membersCount, err := a.Srv().Store.Team().GetActiveMemberCount(tm.TeamId, nil) 732 if err != nil { 733 return nil, false, model.NewAppError("joinUserToTeam", "app.team.get_active_member_count.app_error", nil, err.Error(), http.StatusInternalServerError) 734 } 735 736 if membersCount >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) { 737 return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest) 738 } 739 740 member, nErr := a.Srv().Store.Team().UpdateMember(tm) 741 if nErr != nil { 742 var appErr *model.AppError 743 switch { 744 case errors.As(nErr, &appErr): 745 return nil, false, appErr 746 default: 747 return nil, false, model.NewAppError("joinUserToTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 748 } 749 } 750 751 return member, false, nil 752 } 753 754 func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError { 755 if !a.isTeamEmailAllowed(user, team) { 756 return model.NewAppError("JoinUserToTeam", "api.team.join_user_to_team.allowed_domains.app_error", nil, "", http.StatusBadRequest) 757 } 758 tm, alreadyAdded, err := a.joinUserToTeam(team, user) 759 if err != nil { 760 return err 761 } 762 if alreadyAdded { 763 return nil 764 } 765 766 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 767 var actor *model.User 768 if userRequestorId != "" { 769 actor, _ = a.GetUser(userRequestorId) 770 } 771 772 a.Srv().Go(func() { 773 pluginContext := a.PluginContext() 774 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 775 hooks.UserHasJoinedTeam(pluginContext, tm, actor) 776 return true 777 }, plugin.UserHasJoinedTeamId) 778 }) 779 } 780 781 if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil { 782 return model.NewAppError("JoinUserToTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError) 783 } 784 785 if err := a.createInitialSidebarCategories(user.Id, team.Id); err != nil { 786 mlog.Error( 787 "Encountered an issue creating default sidebar categories.", 788 mlog.String("user_id", user.Id), 789 mlog.String("team_id", team.Id), 790 mlog.Err(err), 791 ) 792 } 793 794 shouldBeAdmin := team.Email == user.Email 795 796 if !user.IsGuest() { 797 // Soft error if there is an issue joining the default channels 798 if err := a.JoinDefaultChannels(team.Id, user, shouldBeAdmin, userRequestorId); err != nil { 799 mlog.Error( 800 "Encountered an issue joining default channels.", 801 mlog.String("user_id", user.Id), 802 mlog.String("team_id", team.Id), 803 mlog.Err(err), 804 ) 805 } 806 } 807 808 a.ClearSessionCacheForUser(user.Id) 809 a.InvalidateCacheForUser(user.Id) 810 a.invalidateCacheForUserTeams(user.Id) 811 812 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil) 813 message.Add("team_id", team.Id) 814 message.Add("user_id", user.Id) 815 a.Publish(message) 816 817 return nil 818 } 819 820 func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) { 821 team, err := a.Srv().Store.Team().Get(teamId) 822 if err != nil { 823 var nfErr *store.ErrNotFound 824 switch { 825 case errors.As(err, &nfErr): 826 return nil, model.NewAppError("GetTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound) 827 default: 828 return nil, model.NewAppError("GetTeam", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 829 } 830 } 831 832 return team, nil 833 } 834 835 func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) { 836 team, err := a.Srv().Store.Team().GetByName(name) 837 if err != nil { 838 var nfErr *store.ErrNotFound 839 switch { 840 case errors.As(err, &nfErr): 841 return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 842 default: 843 return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.app_error", nil, err.Error(), http.StatusNotFound) 844 } 845 } 846 847 return team, nil 848 } 849 850 func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) { 851 team, err := a.Srv().Store.Team().GetByInviteId(inviteId) 852 if err != nil { 853 var nfErr *store.ErrNotFound 854 switch { 855 case errors.As(err, &nfErr): 856 return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 857 default: 858 return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, err.Error(), http.StatusInternalServerError) 859 } 860 } 861 862 return team, nil 863 } 864 865 func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) { 866 teams, err := a.Srv().Store.Team().GetAll() 867 if err != nil { 868 return nil, model.NewAppError("GetAllTeams", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 869 } 870 871 return teams, nil 872 } 873 874 func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) { 875 teams, err := a.Srv().Store.Team().GetAllPage(offset, limit) 876 if err != nil { 877 return nil, model.NewAppError("GetAllTeamsPage", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 878 } 879 880 return teams, nil 881 } 882 883 func (a *App) GetAllTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) { 884 totalCount, err := a.Srv().Store.Team().AnalyticsTeamCount(true) 885 if err != nil { 886 return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError) 887 } 888 teams, err := a.Srv().Store.Team().GetAllPage(offset, limit) 889 if err != nil { 890 return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 891 } 892 return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil 893 } 894 895 func (a *App) GetAllPrivateTeams() ([]*model.Team, *model.AppError) { 896 teams, err := a.Srv().Store.Team().GetAllPrivateTeamListing() 897 if err != nil { 898 return nil, model.NewAppError("GetAllPrivateTeams", "app.team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 899 } 900 901 return teams, nil 902 } 903 904 func (a *App) GetAllPrivateTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) { 905 teams, err := a.Srv().Store.Team().GetAllPrivateTeamPageListing(offset, limit) 906 if err != nil { 907 return nil, model.NewAppError("GetAllPrivateTeamsPage", "app.team.get_all_private_team_page_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 908 } 909 910 return teams, nil 911 } 912 913 func (a *App) GetAllPrivateTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) { 914 totalCount, err := a.Srv().Store.Team().AnalyticsPrivateTeamCount() 915 if err != nil { 916 return nil, model.NewAppError("GetAllPrivateTeamsPageWithCount", "app.team.analytics_private_team_count.app_error", nil, err.Error(), http.StatusInternalServerError) 917 } 918 teams, err := a.Srv().Store.Team().GetAllPrivateTeamPageListing(offset, limit) 919 if err != nil { 920 return nil, model.NewAppError("GetAllPrivateTeamsPageWithCount", "app.team.get_all_private_team_page_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 921 } 922 return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil 923 } 924 925 func (a *App) GetAllPublicTeams() ([]*model.Team, *model.AppError) { 926 teams, err := a.Srv().Store.Team().GetAllTeamListing() 927 if err != nil { 928 return nil, model.NewAppError("GetAllPublicTeams", "app.team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 929 } 930 931 return teams, nil 932 } 933 934 func (a *App) GetAllPublicTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) { 935 teams, err := a.Srv().Store.Team().GetAllTeamPageListing(offset, limit) 936 if err != nil { 937 return nil, model.NewAppError("GetAllPublicTeamsPage", "app.team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 938 } 939 940 return teams, nil 941 } 942 943 func (a *App) GetAllPublicTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) { 944 totalCount, err := a.Srv().Store.Team().AnalyticsPublicTeamCount() 945 if err != nil { 946 return nil, model.NewAppError("GetAllPublicTeamsPageWithCount", "app.team.analytics_public_team_count.app_error", nil, err.Error(), http.StatusInternalServerError) 947 } 948 teams, err := a.Srv().Store.Team().GetAllPublicTeamPageListing(offset, limit) 949 if err != nil { 950 return nil, model.NewAppError("GetAllPublicTeamsPageWithCount", "app.team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError) 951 } 952 return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil 953 } 954 955 // SearchAllTeams returns a team list and the total count of the results 956 func (a *App) SearchAllTeams(searchOpts *model.TeamSearch) ([]*model.Team, int64, *model.AppError) { 957 if searchOpts.IsPaginated() { 958 teams, count, err := a.Srv().Store.Team().SearchAllPaged(searchOpts.Term, searchOpts) 959 if err != nil { 960 return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError) 961 } 962 963 return teams, count, nil 964 } 965 results, err := a.Srv().Store.Team().SearchAll(searchOpts.Term, searchOpts) 966 if err != nil { 967 return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError) 968 } 969 return results, int64(len(results)), nil 970 } 971 972 func (a *App) SearchPublicTeams(term string) ([]*model.Team, *model.AppError) { 973 teams, err := a.Srv().Store.Team().SearchOpen(term) 974 if err != nil { 975 return nil, model.NewAppError("SearchPublicTeams", "app.team.search_open_team.app_error", nil, err.Error(), http.StatusInternalServerError) 976 } 977 978 return teams, nil 979 } 980 981 func (a *App) SearchPrivateTeams(term string) ([]*model.Team, *model.AppError) { 982 teams, err := a.Srv().Store.Team().SearchPrivate(term) 983 if err != nil { 984 return nil, model.NewAppError("SearchPrivateTeams", "app.team.search_private_team.app_error", nil, err.Error(), http.StatusInternalServerError) 985 } 986 987 return teams, nil 988 } 989 990 func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) { 991 teams, err := a.Srv().Store.Team().GetTeamsByUserId(userId) 992 if err != nil { 993 return nil, model.NewAppError("GetTeamsForUser", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 994 } 995 996 return teams, nil 997 } 998 999 func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { 1000 teamMember, err := a.Srv().Store.Team().GetMember(teamId, userId) 1001 if err != nil { 1002 var nfErr *store.ErrNotFound 1003 switch { 1004 case errors.As(err, &nfErr): 1005 return nil, model.NewAppError("GetTeamMember", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1006 default: 1007 return nil, model.NewAppError("GetTeamMember", "app.team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError) 1008 } 1009 } 1010 1011 return teamMember, nil 1012 } 1013 1014 func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) { 1015 teamMembers, err := a.Srv().Store.Team().GetTeamsForUser(context.Background(), userId) 1016 if err != nil { 1017 return nil, model.NewAppError("GetTeamMembersForUser", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError) 1018 } 1019 1020 return teamMembers, nil 1021 } 1022 1023 func (a *App) GetTeamMembersForUserWithPagination(userId string, page, perPage int) ([]*model.TeamMember, *model.AppError) { 1024 teamMembers, err := a.Srv().Store.Team().GetTeamsForUserWithPagination(userId, page, perPage) 1025 if err != nil { 1026 return nil, model.NewAppError("GetTeamMembersForUserWithPagination", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError) 1027 } 1028 1029 return teamMembers, nil 1030 } 1031 1032 func (a *App) GetTeamMembers(teamId string, offset int, limit int, teamMembersGetOptions *model.TeamMembersGetOptions) ([]*model.TeamMember, *model.AppError) { 1033 teamMembers, err := a.Srv().Store.Team().GetMembers(teamId, offset, limit, teamMembersGetOptions) 1034 if err != nil { 1035 return nil, model.NewAppError("GetTeamMembers", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError) 1036 } 1037 1038 return teamMembers, nil 1039 } 1040 1041 func (a *App) GetTeamMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) { 1042 teamMembers, err := a.Srv().Store.Team().GetMembersByIds(teamId, userIds, restrictions) 1043 if err != nil { 1044 return nil, model.NewAppError("GetTeamMembersByIds", "app.team.get_members_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError) 1045 } 1046 1047 return teamMembers, nil 1048 } 1049 1050 func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { 1051 if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil { 1052 return nil, err 1053 } 1054 1055 teamMember, err := a.GetTeamMember(teamId, userId) 1056 if err != nil { 1057 return nil, err 1058 } 1059 1060 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil) 1061 message.Add("team_id", teamId) 1062 message.Add("user_id", userId) 1063 a.Publish(message) 1064 1065 return teamMember, nil 1066 } 1067 1068 func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string, graceful bool) ([]*model.TeamMemberWithError, *model.AppError) { 1069 var membersWithErrors []*model.TeamMemberWithError 1070 1071 for _, userId := range userIds { 1072 if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil { 1073 if graceful { 1074 membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{ 1075 UserId: userId, 1076 Error: err, 1077 }) 1078 continue 1079 } 1080 return nil, err 1081 } 1082 1083 teamMember, err := a.GetTeamMember(teamId, userId) 1084 if err != nil { 1085 return nil, err 1086 } 1087 membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{ 1088 UserId: userId, 1089 Member: teamMember, 1090 }) 1091 1092 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil) 1093 message.Add("team_id", teamId) 1094 message.Add("user_id", userId) 1095 a.Publish(message) 1096 } 1097 1098 return membersWithErrors, nil 1099 } 1100 1101 func (a *App) AddTeamMemberByToken(userId, tokenId string) (*model.TeamMember, *model.AppError) { 1102 team, err := a.AddUserToTeamByToken(userId, tokenId) 1103 if err != nil { 1104 return nil, err 1105 } 1106 1107 teamMember, err := a.GetTeamMember(team.Id, userId) 1108 if err != nil { 1109 return nil, err 1110 } 1111 1112 return teamMember, nil 1113 } 1114 1115 func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) { 1116 team, err := a.AddUserToTeamByInviteId(inviteId, userId) 1117 if err != nil { 1118 return nil, err 1119 } 1120 1121 if team.IsGroupConstrained() { 1122 return nil, model.NewAppError("AddTeamMemberByInviteId", "app.team.invite_id.group_constrained.error", nil, "", http.StatusForbidden) 1123 } 1124 1125 teamMember, err := a.GetTeamMember(team.Id, userId) 1126 if err != nil { 1127 return nil, err 1128 } 1129 return teamMember, nil 1130 } 1131 1132 func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) { 1133 channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamId, userId) 1134 if err != nil { 1135 return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError) 1136 } 1137 1138 var teamUnread = &model.TeamUnread{ 1139 MsgCount: 0, 1140 MentionCount: 0, 1141 TeamId: teamId, 1142 } 1143 1144 for _, cu := range channelUnreads { 1145 teamUnread.MentionCount += cu.MentionCount 1146 1147 if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION { 1148 teamUnread.MsgCount += cu.MsgCount 1149 } 1150 } 1151 1152 return teamUnread, nil 1153 } 1154 1155 func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError { 1156 tchan := make(chan store.StoreResult, 1) 1157 go func() { 1158 team, err := a.Srv().Store.Team().Get(teamId) 1159 tchan <- store.StoreResult{Data: team, NErr: err} 1160 close(tchan) 1161 }() 1162 1163 uchan := make(chan store.StoreResult, 1) 1164 go func() { 1165 user, err := a.Srv().Store.User().Get(userId) 1166 uchan <- store.StoreResult{Data: user, NErr: err} 1167 close(uchan) 1168 }() 1169 1170 result := <-tchan 1171 if result.NErr != nil { 1172 var nfErr *store.ErrNotFound 1173 switch { 1174 case errors.As(result.NErr, &nfErr): 1175 return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 1176 default: 1177 return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1178 } 1179 } 1180 team := result.Data.(*model.Team) 1181 1182 result = <-uchan 1183 if result.NErr != nil { 1184 var nfErr *store.ErrNotFound 1185 switch { 1186 case errors.As(result.NErr, &nfErr): 1187 return model.NewAppError("RemoveUserFromTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 1188 default: 1189 return model.NewAppError("RemoveUserFromTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1190 } 1191 } 1192 user := result.Data.(*model.User) 1193 1194 if err := a.LeaveTeam(team, user, requestorId); err != nil { 1195 return err 1196 } 1197 1198 return nil 1199 } 1200 1201 func (a *App) RemoveTeamMemberFromTeam(teamMember *model.TeamMember, requestorId string) *model.AppError { 1202 // Send the websocket message before we actually do the remove so the user being removed gets it. 1203 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, teamMember.TeamId, "", "", nil) 1204 message.Add("user_id", teamMember.UserId) 1205 message.Add("team_id", teamMember.TeamId) 1206 a.Publish(message) 1207 1208 user, nErr := a.Srv().Store.User().Get(teamMember.UserId) 1209 if nErr != nil { 1210 var nfErr *store.ErrNotFound 1211 switch { 1212 case errors.As(nErr, &nfErr): 1213 return model.NewAppError("RemoveTeamMemberFromTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 1214 default: 1215 return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1216 } 1217 } 1218 1219 teamMember.Roles = "" 1220 teamMember.DeleteAt = model.GetMillis() 1221 1222 if _, nErr := a.Srv().Store.Team().UpdateMember(teamMember); nErr != nil { 1223 var appErr *model.AppError 1224 switch { 1225 case errors.As(nErr, &appErr): 1226 return appErr 1227 default: 1228 return model.NewAppError("RemoveTeamMemberFromTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1229 } 1230 } 1231 1232 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 1233 var actor *model.User 1234 if requestorId != "" { 1235 actor, _ = a.GetUser(requestorId) 1236 } 1237 1238 a.Srv().Go(func() { 1239 pluginContext := a.PluginContext() 1240 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 1241 hooks.UserHasLeftTeam(pluginContext, teamMember, actor) 1242 return true 1243 }, plugin.UserHasLeftTeamId) 1244 }) 1245 } 1246 1247 if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil { 1248 return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError) 1249 } 1250 1251 if err := a.Srv().Store.Channel().ClearSidebarOnTeamLeave(user.Id, teamMember.TeamId); err != nil { 1252 return model.NewAppError("RemoveTeamMemberFromTeam", "app.channel.sidebar_categories.app_error", nil, err.Error(), http.StatusInternalServerError) 1253 } 1254 1255 // delete the preferences that set the last channel used in the team and other team specific preferences 1256 if err := a.Srv().Store.Preference().DeleteCategory(user.Id, teamMember.TeamId); err != nil { 1257 return model.NewAppError("RemoveTeamMemberFromTeam", "app.preference.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1258 } 1259 1260 a.ClearSessionCacheForUser(user.Id) 1261 a.InvalidateCacheForUser(user.Id) 1262 a.invalidateCacheForUserTeams(user.Id) 1263 1264 return nil 1265 } 1266 1267 func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError { 1268 teamMember, err := a.GetTeamMember(team.Id, user.Id) 1269 if err != nil { 1270 return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest) 1271 } 1272 1273 var channelList *model.ChannelList 1274 1275 var nErr error 1276 if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, true, 0); nErr != nil { 1277 var nfErr *store.ErrNotFound 1278 if errors.As(nErr, &nfErr) { 1279 channelList = &model.ChannelList{} 1280 } else { 1281 return model.NewAppError("LeaveTeam", "app.channel.get_channels.get.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1282 } 1283 } 1284 1285 for _, channel := range *channelList { 1286 if !channel.IsGroupOrDirect() { 1287 a.invalidateCacheForChannelMembers(channel.Id) 1288 if nErr = a.Srv().Store.Channel().RemoveMember(channel.Id, user.Id); nErr != nil { 1289 return model.NewAppError("LeaveTeam", "app.channel.remove_member.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1290 } 1291 } 1292 } 1293 1294 channel, nErr := a.Srv().Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false) 1295 if nErr != nil { 1296 var nfErr *store.ErrNotFound 1297 switch { 1298 case errors.As(nErr, &nfErr): 1299 return model.NewAppError("LeaveTeam", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1300 default: 1301 return model.NewAppError("LeaveTeam", "app.channel.get_by_name.existing.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1302 } 1303 } 1304 1305 if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 1306 if requestorId == user.Id { 1307 if err = a.postLeaveTeamMessage(user, channel); err != nil { 1308 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 1309 } 1310 } else { 1311 if err = a.postRemoveFromTeamMessage(user, channel); err != nil { 1312 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 1313 } 1314 } 1315 } 1316 1317 if err := a.RemoveTeamMemberFromTeam(teamMember, requestorId); err != nil { 1318 return err 1319 } 1320 1321 return nil 1322 } 1323 1324 func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 1325 post := &model.Post{ 1326 ChannelId: channel.Id, 1327 Message: fmt.Sprintf(utils.T("api.team.leave.left"), user.Username), 1328 Type: model.POST_LEAVE_TEAM, 1329 UserId: user.Id, 1330 Props: model.StringInterface{ 1331 "username": user.Username, 1332 }, 1333 } 1334 1335 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1336 return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1337 } 1338 1339 return nil 1340 } 1341 1342 func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 1343 post := &model.Post{ 1344 ChannelId: channel.Id, 1345 Message: fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username), 1346 Type: model.POST_REMOVE_FROM_TEAM, 1347 UserId: user.Id, 1348 Props: model.StringInterface{ 1349 "username": user.Username, 1350 }, 1351 } 1352 1353 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1354 return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1355 } 1356 1357 return nil 1358 } 1359 1360 func (a *App) prepareInviteNewUsersToTeam(teamId, senderId string) (*model.User, *model.Team, *model.AppError) { 1361 tchan := make(chan store.StoreResult, 1) 1362 go func() { 1363 team, err := a.Srv().Store.Team().Get(teamId) 1364 tchan <- store.StoreResult{Data: team, NErr: err} 1365 close(tchan) 1366 }() 1367 1368 uchan := make(chan store.StoreResult, 1) 1369 go func() { 1370 user, err := a.Srv().Store.User().Get(senderId) 1371 uchan <- store.StoreResult{Data: user, NErr: err} 1372 close(uchan) 1373 }() 1374 1375 result := <-tchan 1376 if result.NErr != nil { 1377 var nfErr *store.ErrNotFound 1378 switch { 1379 case errors.As(result.NErr, &nfErr): 1380 return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 1381 default: 1382 return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1383 } 1384 } 1385 team := result.Data.(*model.Team) 1386 1387 result = <-uchan 1388 if result.NErr != nil { 1389 var nfErr *store.ErrNotFound 1390 switch { 1391 case errors.As(result.NErr, &nfErr): 1392 return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 1393 default: 1394 return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1395 } 1396 } 1397 user := result.Data.(*model.User) 1398 return user, team, nil 1399 } 1400 1401 func genEmailInviteWithErrorList(emailList []string) []*model.EmailInviteWithError { 1402 invitesNotSent := make([]*model.EmailInviteWithError, len(emailList)) 1403 for i := range emailList { 1404 invite := &model.EmailInviteWithError{ 1405 Email: emailList[i], 1406 Error: model.NewAppError("inviteUsersToTeam", "api.team.invite_members.limit_reached.app_error", map[string]interface{}{"Addresses": emailList[i]}, "", http.StatusBadRequest), 1407 } 1408 invitesNotSent[i] = invite 1409 } 1410 return invitesNotSent 1411 } 1412 1413 func (a *App) GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError) { 1414 var invitesNotSent []*model.EmailInviteWithError 1415 if cloudUserLimit <= 0 { 1416 return emailList, invitesNotSent, nil 1417 } 1418 systemUserCount, _ := a.Srv().Store.User().Count(model.UserCountOptions{}) 1419 remainingUsers := cloudUserLimit - systemUserCount 1420 if remainingUsers <= 0 { 1421 // No remaining users so all fail 1422 invitesNotSent = genEmailInviteWithErrorList(emailList) 1423 emailList = nil 1424 } else if remainingUsers < int64(len(emailList)) { 1425 // Trim the email list to only invite as many users as are remaining in subscription 1426 // Set graceful errors for the remaining email addresses 1427 emailsAboveLimit := emailList[remainingUsers:] 1428 invitesNotSent = genEmailInviteWithErrorList(emailsAboveLimit) 1429 // If 1 user remaining we have to prevent 0:0 reslicing 1430 if remainingUsers == 1 { 1431 email := emailList[0] 1432 emailList = nil 1433 emailList = append(emailList, email) 1434 } else { 1435 emailList = emailList[:(remainingUsers - 1)] 1436 } 1437 } 1438 1439 return emailList, invitesNotSent, nil 1440 } 1441 1442 func (a *App) InviteNewUsersToTeamGracefully(emailList []string, teamId, senderId string) ([]*model.EmailInviteWithError, *model.AppError) { 1443 if !*a.Config().ServiceSettings.EnableEmailInvitations { 1444 return nil, model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented) 1445 } 1446 1447 if len(emailList) == 0 { 1448 err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest) 1449 return nil, err 1450 } 1451 user, team, err := a.prepareInviteNewUsersToTeam(teamId, senderId) 1452 if err != nil { 1453 return nil, err 1454 } 1455 allowedDomains := a.getAllowedDomains(user, team) 1456 var inviteListWithErrors []*model.EmailInviteWithError 1457 var goodEmails []string 1458 for _, email := range emailList { 1459 invite := &model.EmailInviteWithError{ 1460 Email: email, 1461 Error: nil, 1462 } 1463 if !a.isEmailAddressAllowed(email, allowedDomains) { 1464 invite.Error = model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest) 1465 } else { 1466 goodEmails = append(goodEmails, email) 1467 } 1468 inviteListWithErrors = append(inviteListWithErrors, invite) 1469 } 1470 1471 if len(goodEmails) > 0 { 1472 nameFormat := *a.Config().TeamSettings.TeammateNameDisplay 1473 err = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, goodEmails, a.GetSiteURL()) 1474 if err != nil { 1475 return nil, err 1476 } 1477 } 1478 1479 return inviteListWithErrors, nil 1480 } 1481 1482 func (a *App) prepareInviteGuestsToChannels(teamId string, guestsInvite *model.GuestsInvite, senderId string) (*model.User, *model.Team, []*model.Channel, *model.AppError) { 1483 if err := guestsInvite.IsValid(); err != nil { 1484 return nil, nil, nil, err 1485 } 1486 1487 tchan := make(chan store.StoreResult, 1) 1488 go func() { 1489 team, err := a.Srv().Store.Team().Get(teamId) 1490 tchan <- store.StoreResult{Data: team, NErr: err} 1491 close(tchan) 1492 }() 1493 cchan := make(chan store.StoreResult, 1) 1494 go func() { 1495 channels, err := a.Srv().Store.Channel().GetChannelsByIds(guestsInvite.Channels, false) 1496 cchan <- store.StoreResult{Data: channels, NErr: err} 1497 close(cchan) 1498 }() 1499 uchan := make(chan store.StoreResult, 1) 1500 go func() { 1501 user, err := a.Srv().Store.User().Get(senderId) 1502 uchan <- store.StoreResult{Data: user, NErr: err} 1503 close(uchan) 1504 }() 1505 1506 result := <-cchan 1507 if result.NErr != nil { 1508 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.channel.get_channels_by_ids.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1509 } 1510 channels := result.Data.([]*model.Channel) 1511 1512 result = <-uchan 1513 if result.NErr != nil { 1514 var nfErr *store.ErrNotFound 1515 switch { 1516 case errors.As(result.NErr, &nfErr): 1517 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound) 1518 default: 1519 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1520 } 1521 } 1522 user := result.Data.(*model.User) 1523 1524 result = <-tchan 1525 if result.NErr != nil { 1526 var nfErr *store.ErrNotFound 1527 switch { 1528 case errors.As(result.NErr, &nfErr): 1529 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound) 1530 default: 1531 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1532 } 1533 } 1534 team := result.Data.(*model.Team) 1535 1536 for _, channel := range channels { 1537 if channel.TeamId != teamId { 1538 return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "api.team.invite_guests.channel_in_invalid_team.app_error", nil, "", http.StatusBadRequest) 1539 } 1540 } 1541 return user, team, channels, nil 1542 } 1543 1544 func (a *App) InviteGuestsToChannelsGracefully(teamId string, guestsInvite *model.GuestsInvite, senderId string) ([]*model.EmailInviteWithError, *model.AppError) { 1545 if !*a.Config().ServiceSettings.EnableEmailInvitations { 1546 return nil, model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented) 1547 } 1548 1549 user, team, channels, err := a.prepareInviteGuestsToChannels(teamId, guestsInvite, senderId) 1550 if err != nil { 1551 return nil, err 1552 } 1553 1554 var inviteListWithErrors []*model.EmailInviteWithError 1555 var goodEmails []string 1556 for _, email := range guestsInvite.Emails { 1557 invite := &model.EmailInviteWithError{ 1558 Email: email, 1559 Error: nil, 1560 } 1561 if !CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) { 1562 invite.Error = model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest) 1563 } else { 1564 goodEmails = append(goodEmails, email) 1565 } 1566 inviteListWithErrors = append(inviteListWithErrors, invite) 1567 } 1568 1569 if len(goodEmails) > 0 { 1570 nameFormat := *a.Config().TeamSettings.TeammateNameDisplay 1571 senderProfileImage, _, err := a.GetProfileImage(user) 1572 if err != nil { 1573 a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err)) 1574 } 1575 err = a.Srv().EmailService.sendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), guestsInvite.Message) 1576 if err != nil { 1577 return nil, err 1578 } 1579 } 1580 1581 return inviteListWithErrors, nil 1582 } 1583 1584 func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError { 1585 if !*a.Config().ServiceSettings.EnableEmailInvitations { 1586 return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented) 1587 } 1588 1589 if len(emailList) == 0 { 1590 err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest) 1591 return err 1592 } 1593 1594 user, team, err := a.prepareInviteNewUsersToTeam(teamId, senderId) 1595 if err != nil { 1596 return err 1597 } 1598 1599 allowedDomains := a.getAllowedDomains(user, team) 1600 var invalidEmailList []string 1601 1602 for _, email := range emailList { 1603 if !a.isEmailAddressAllowed(email, allowedDomains) { 1604 invalidEmailList = append(invalidEmailList, email) 1605 } 1606 } 1607 1608 if len(invalidEmailList) > 0 { 1609 s := strings.Join(invalidEmailList, ", ") 1610 return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest) 1611 } 1612 1613 nameFormat := *a.Config().TeamSettings.TeammateNameDisplay 1614 err = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL()) 1615 if err != nil { 1616 return err 1617 } 1618 1619 return nil 1620 } 1621 1622 func (a *App) InviteGuestsToChannels(teamId string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError { 1623 if !*a.Config().ServiceSettings.EnableEmailInvitations { 1624 return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented) 1625 } 1626 1627 user, team, channels, err := a.prepareInviteGuestsToChannels(teamId, guestsInvite, senderId) 1628 if err != nil { 1629 return err 1630 } 1631 1632 var invalidEmailList []string 1633 for _, email := range guestsInvite.Emails { 1634 if !CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) { 1635 invalidEmailList = append(invalidEmailList, email) 1636 } 1637 } 1638 1639 if len(invalidEmailList) > 0 { 1640 s := strings.Join(invalidEmailList, ", ") 1641 return model.NewAppError("InviteGuestsToChannels", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest) 1642 } 1643 1644 nameFormat := *a.Config().TeamSettings.TeammateNameDisplay 1645 senderProfileImage, _, err := a.GetProfileImage(user) 1646 if err != nil { 1647 a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err)) 1648 } 1649 err = a.Srv().EmailService.sendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, guestsInvite.Emails, a.GetSiteURL(), guestsInvite.Message) 1650 if err != nil { 1651 return err 1652 } 1653 1654 return nil 1655 } 1656 1657 func (a *App) FindTeamByName(name string) bool { 1658 if _, err := a.Srv().Store.Team().GetByName(name); err != nil { 1659 return false 1660 } 1661 return true 1662 } 1663 1664 func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) { 1665 data, err := a.Srv().Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId) 1666 if err != nil { 1667 return nil, model.NewAppError("GetTeamsUnreadForUser", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError) 1668 } 1669 1670 members := []*model.TeamUnread{} 1671 membersMap := make(map[string]*model.TeamUnread) 1672 1673 unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread { 1674 tu.MentionCount += cu.MentionCount 1675 1676 if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION { 1677 tu.MsgCount += cu.MsgCount 1678 } 1679 1680 return tu 1681 } 1682 1683 for i := range data { 1684 id := data[i].TeamId 1685 if mu, ok := membersMap[id]; ok { 1686 membersMap[id] = unreads(data[i], mu) 1687 } else { 1688 membersMap[id] = unreads(data[i], &model.TeamUnread{ 1689 MsgCount: 0, 1690 MentionCount: 0, 1691 TeamId: id, 1692 }) 1693 } 1694 } 1695 1696 for _, val := range membersMap { 1697 members = append(members, val) 1698 } 1699 1700 return members, nil 1701 } 1702 1703 func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError { 1704 team, err := a.GetTeam(teamId) 1705 if err != nil { 1706 return err 1707 } 1708 1709 return a.PermanentDeleteTeam(team) 1710 } 1711 1712 func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError { 1713 team.DeleteAt = model.GetMillis() 1714 if _, err := a.Srv().Store.Team().Update(team); err != nil { 1715 var invErr *store.ErrInvalidInput 1716 var appErr *model.AppError 1717 switch { 1718 case errors.As(err, &invErr): 1719 return model.NewAppError("PermanentDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1720 case errors.As(err, &appErr): 1721 return appErr 1722 default: 1723 return model.NewAppError("PermanentDeleteTeam", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError) 1724 } 1725 } 1726 1727 if channels, err := a.Srv().Store.Channel().GetTeamChannels(team.Id); err != nil { 1728 var nfErr *store.ErrNotFound 1729 if !errors.As(err, &nfErr) { 1730 return model.NewAppError("PermanentDeleteTeam", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError) 1731 } 1732 } else { 1733 for _, c := range *channels { 1734 a.PermanentDeleteChannel(c) 1735 } 1736 } 1737 1738 if err := a.Srv().Store.Team().RemoveAllMembersByTeam(team.Id); err != nil { 1739 return model.NewAppError("PermanentDeleteTeam", "app.team.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError) 1740 } 1741 1742 if err := a.Srv().Store.Command().PermanentDeleteByTeam(team.Id); err != nil { 1743 return model.NewAppError("PermanentDeleteTeam", "app.team.permanentdeleteteam.internal_error", nil, err.Error(), http.StatusInternalServerError) 1744 } 1745 1746 if err := a.Srv().Store.Team().PermanentDelete(team.Id); err != nil { 1747 return model.NewAppError("PermanentDeleteTeam", "app.team.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1748 } 1749 1750 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM) 1751 1752 return nil 1753 } 1754 1755 func (a *App) SoftDeleteTeam(teamId string) *model.AppError { 1756 team, err := a.GetTeam(teamId) 1757 if err != nil { 1758 return err 1759 } 1760 1761 team.DeleteAt = model.GetMillis() 1762 team, nErr := a.Srv().Store.Team().Update(team) 1763 if nErr != nil { 1764 var invErr *store.ErrInvalidInput 1765 var appErr *model.AppError 1766 switch { 1767 case errors.As(nErr, &invErr): 1768 return model.NewAppError("SoftDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1769 case errors.As(nErr, &appErr): 1770 return appErr 1771 default: 1772 return model.NewAppError("SoftDeleteTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1773 } 1774 } 1775 1776 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM) 1777 1778 return nil 1779 } 1780 1781 func (a *App) RestoreTeam(teamId string) *model.AppError { 1782 team, err := a.GetTeam(teamId) 1783 if err != nil { 1784 return err 1785 } 1786 1787 team.DeleteAt = 0 1788 team, nErr := a.Srv().Store.Team().Update(team) 1789 if nErr != nil { 1790 var invErr *store.ErrInvalidInput 1791 var appErr *model.AppError 1792 switch { 1793 case errors.As(nErr, &invErr): 1794 return model.NewAppError("RestoreTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest) 1795 case errors.As(nErr, &appErr): 1796 return appErr 1797 default: 1798 return model.NewAppError("RestoreTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1799 } 1800 } 1801 1802 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_RESTORE_TEAM) 1803 return nil 1804 } 1805 1806 func (a *App) GetTeamStats(teamId string, restrictions *model.ViewUsersRestrictions) (*model.TeamStats, *model.AppError) { 1807 tchan := make(chan store.StoreResult, 1) 1808 go func() { 1809 totalMemberCount, err := a.Srv().Store.Team().GetTotalMemberCount(teamId, restrictions) 1810 tchan <- store.StoreResult{Data: totalMemberCount, NErr: err} 1811 close(tchan) 1812 }() 1813 achan := make(chan store.StoreResult, 1) 1814 go func() { 1815 memberCount, err := a.Srv().Store.Team().GetActiveMemberCount(teamId, restrictions) 1816 achan <- store.StoreResult{Data: memberCount, NErr: err} 1817 close(achan) 1818 }() 1819 1820 stats := &model.TeamStats{} 1821 stats.TeamId = teamId 1822 1823 result := <-tchan 1824 if result.NErr != nil { 1825 return nil, model.NewAppError("GetTeamStats", "app.team.get_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1826 } 1827 stats.TotalMemberCount = result.Data.(int64) 1828 1829 result = <-achan 1830 if result.NErr != nil { 1831 return nil, model.NewAppError("GetTeamStats", "app.team.get_active_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError) 1832 } 1833 stats.ActiveMemberCount = result.Data.(int64) 1834 1835 return stats, nil 1836 } 1837 1838 func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) { 1839 tokenId := query.Get("t") 1840 inviteId := query.Get("id") 1841 1842 if len(tokenId) > 0 { 1843 token, err := a.Srv().Store.Token().GetByToken(tokenId) 1844 if err != nil { 1845 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest) 1846 } 1847 1848 if token.Type != TOKEN_TYPE_TEAM_INVITATION && token.Type != TOKEN_TYPE_GUEST_INVITATION { 1849 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest) 1850 } 1851 1852 if model.GetMillis()-token.CreateAt >= INVITATION_EXPIRY_TIME { 1853 a.DeleteToken(token) 1854 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest) 1855 } 1856 1857 tokenData := model.MapFromJson(strings.NewReader(token.Extra)) 1858 1859 return tokenData["teamId"], nil 1860 } 1861 if len(inviteId) > 0 { 1862 team, err := a.Srv().Store.Team().GetByInviteId(inviteId) 1863 if err == nil { 1864 return team.Id, nil 1865 } 1866 // soft fail, so we still create user but don't auto-join team 1867 mlog.Error("error getting team by inviteId.", mlog.String("invite_id", inviteId), mlog.Err(err)) 1868 } 1869 1870 return "", nil 1871 } 1872 1873 func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team { 1874 if a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) { 1875 return team 1876 } 1877 1878 if a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_INVITE_USER) { 1879 inviteId := team.InviteId 1880 team.Sanitize() 1881 team.InviteId = inviteId 1882 return team 1883 } 1884 1885 team.Sanitize() 1886 1887 return team 1888 } 1889 1890 func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team { 1891 for _, team := range teams { 1892 a.SanitizeTeam(session, team) 1893 } 1894 1895 return teams 1896 } 1897 1898 func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) { 1899 if len(*a.Config().FileSettings.DriverName) == 0 { 1900 return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented) 1901 } 1902 1903 path := "teams/" + team.Id + "/teamIcon.png" 1904 data, err := a.ReadFile(path) 1905 if err != nil { 1906 return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound) 1907 } 1908 1909 return data, nil 1910 } 1911 1912 func (a *App) SetTeamIcon(teamId string, imageData *multipart.FileHeader) *model.AppError { 1913 file, err := imageData.Open() 1914 if err != nil { 1915 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest) 1916 } 1917 defer file.Close() 1918 return a.SetTeamIconFromMultiPartFile(teamId, file) 1919 } 1920 1921 func (a *App) SetTeamIconFromMultiPartFile(teamId string, file multipart.File) *model.AppError { 1922 team, getTeamErr := a.GetTeam(teamId) 1923 1924 if getTeamErr != nil { 1925 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest) 1926 } 1927 1928 if len(*a.Config().FileSettings.DriverName) == 0 { 1929 return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented) 1930 } 1931 1932 // Decode image config first to check dimensions before loading the whole thing into memory later on 1933 config, _, err := image.DecodeConfig(file) 1934 if err != nil { 1935 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode_config.app_error", nil, err.Error(), http.StatusBadRequest) 1936 } 1937 1938 // This casting is done to prevent overflow on 32 bit systems (not needed 1939 // in 64 bits systems because images can't have more than 32 bits height or 1940 // width) 1941 if int64(config.Width)*int64(config.Height) > model.MaxImageSize { 1942 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, "", http.StatusBadRequest) 1943 } 1944 1945 file.Seek(0, 0) 1946 1947 return a.SetTeamIconFromFile(team, file) 1948 } 1949 1950 func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError { 1951 // Decode image into Image object 1952 img, _, err := image.Decode(file) 1953 if err != nil { 1954 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest) 1955 } 1956 1957 orientation, _ := getImageOrientation(file) 1958 img = makeImageUpright(img, orientation) 1959 1960 // Scale team icon 1961 teamIconWidthAndHeight := 128 1962 img = imaging.Fill(img, teamIconWidthAndHeight, teamIconWidthAndHeight, imaging.Center, imaging.Lanczos) 1963 1964 buf := new(bytes.Buffer) 1965 err = png.Encode(buf, img) 1966 if err != nil { 1967 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError) 1968 } 1969 1970 path := "teams/" + team.Id + "/teamIcon.png" 1971 1972 if _, err := a.WriteFile(buf, path); err != nil { 1973 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, "", http.StatusInternalServerError) 1974 } 1975 1976 curTime := model.GetMillis() 1977 1978 if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(team.Id, curTime); err != nil { 1979 return model.NewAppError("SetTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest) 1980 } 1981 1982 // manually set time to avoid possible cluster inconsistencies 1983 team.LastTeamIconUpdate = curTime 1984 1985 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM) 1986 1987 return nil 1988 } 1989 1990 func (a *App) RemoveTeamIcon(teamId string) *model.AppError { 1991 team, err := a.GetTeam(teamId) 1992 if err != nil { 1993 return model.NewAppError("RemoveTeamIcon", "api.team.remove_team_icon.get_team.app_error", nil, err.Error(), http.StatusBadRequest) 1994 } 1995 1996 if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(teamId, 0); err != nil { 1997 return model.NewAppError("RemoveTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest) 1998 } 1999 2000 team.LastTeamIconUpdate = 0 2001 2002 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM) 2003 2004 return nil 2005 } 2006 2007 func (a *App) InvalidateAllEmailInvites() *model.AppError { 2008 if err := a.Srv().Store.Token().RemoveAllTokensByType(TOKEN_TYPE_TEAM_INVITATION); err != nil { 2009 return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest) 2010 } 2011 if err := a.Srv().Store.Token().RemoveAllTokensByType(TOKEN_TYPE_GUEST_INVITATION); err != nil { 2012 return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest) 2013 } 2014 return nil 2015 } 2016 2017 func (a *App) ClearTeamMembersCache(teamID string) { 2018 perPage := 100 2019 page := 0 2020 2021 for { 2022 teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, page*perPage, perPage, nil) 2023 if err != nil { 2024 a.Log().Warn("error clearing cache for team members", mlog.String("team_id", teamID), mlog.String("err", err.Error())) 2025 break 2026 } 2027 2028 for _, teamMember := range teamMembers { 2029 a.ClearSessionCacheForUser(teamMember.UserId) 2030 2031 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", teamMember.UserId, nil) 2032 message.Add("member", teamMember.ToJson()) 2033 a.Publish(message) 2034 } 2035 2036 length := len(teamMembers) 2037 if length < perPage { 2038 break 2039 } 2040 2041 page++ 2042 } 2043 }