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