github.com/spline-fu/mattermost-server@v4.10.10+incompatible/app/team.go (about) 1 // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "bytes" 8 "fmt" 9 "image" 10 "image/png" 11 "mime/multipart" 12 "net/http" 13 "net/url" 14 "strings" 15 16 "github.com/disintegration/imaging" 17 18 "github.com/mattermost/mattermost-server/mlog" 19 "github.com/mattermost/mattermost-server/model" 20 "github.com/mattermost/mattermost-server/utils" 21 ) 22 23 func (a *App) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { 24 if result := <-a.Srv.Store.Team().Save(team); result.Err != nil { 25 return nil, result.Err 26 } else { 27 rteam := result.Data.(*model.Team) 28 29 if _, err := a.CreateDefaultChannels(rteam.Id); err != nil { 30 return nil, err 31 } 32 33 return rteam, nil 34 } 35 } 36 37 func (a *App) CreateTeamWithUser(team *model.Team, userId string) (*model.Team, *model.AppError) { 38 var user *model.User 39 var err *model.AppError 40 if user, err = a.GetUser(userId); err != nil { 41 return nil, err 42 } else { 43 team.Email = user.Email 44 } 45 46 if !a.isTeamEmailAllowed(user) { 47 return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest) 48 } 49 50 var rteam *model.Team 51 if rteam, err = a.CreateTeam(team); err != nil { 52 return nil, err 53 } 54 55 if err = a.JoinUserToTeam(rteam, user, ""); err != nil { 56 return nil, err 57 } 58 59 return rteam, nil 60 } 61 62 func (a *App) isTeamEmailAddressAllowed(email string) bool { 63 email = strings.ToLower(email) 64 // commas and @ signs are optional 65 // can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org 66 domains := strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(a.Config().TeamSettings.RestrictCreationToDomains, "@", " ", -1), ",", " ", -1)))) 67 68 matched := false 69 for _, d := range domains { 70 if strings.HasSuffix(email, "@"+d) { 71 matched = true 72 break 73 } 74 } 75 76 if len(a.Config().TeamSettings.RestrictCreationToDomains) > 0 && !matched { 77 return false 78 } 79 80 return true 81 } 82 83 func (a *App) isTeamEmailAllowed(user *model.User) bool { 84 email := strings.ToLower(user.Email) 85 86 if len(user.AuthService) > 0 && len(*user.AuthData) > 0 { 87 return true 88 } 89 90 return a.isTeamEmailAddressAllowed(email) 91 } 92 93 func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) { 94 var oldTeam *model.Team 95 var err *model.AppError 96 if oldTeam, err = a.GetTeam(team.Id); err != nil { 97 return nil, err 98 } 99 100 oldTeam.DisplayName = team.DisplayName 101 oldTeam.Description = team.Description 102 oldTeam.InviteId = team.InviteId 103 oldTeam.AllowOpenInvite = team.AllowOpenInvite 104 oldTeam.CompanyName = team.CompanyName 105 oldTeam.AllowedDomains = team.AllowedDomains 106 oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate 107 108 if result := <-a.Srv.Store.Team().Update(oldTeam); result.Err != nil { 109 return nil, result.Err 110 } 111 112 a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM) 113 114 return oldTeam, nil 115 } 116 117 func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *model.AppError) { 118 team, err := a.GetTeam(teamId) 119 if err != nil { 120 return nil, err 121 } 122 123 team.Patch(patch) 124 125 updatedTeam, err := a.UpdateTeam(team) 126 if err != nil { 127 return nil, err 128 } 129 130 a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM) 131 132 return updatedTeam, nil 133 } 134 135 func (a *App) sendTeamEvent(team *model.Team, event string) { 136 sanitizedTeam := &model.Team{} 137 *sanitizedTeam = *team 138 sanitizedTeam.Sanitize() 139 140 message := model.NewWebSocketEvent(event, "", "", "", nil) 141 message.Add("team", sanitizedTeam.ToJson()) 142 a.Publish(message) 143 } 144 145 func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) { 146 var member *model.TeamMember 147 if result := <-a.Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil { 148 return nil, result.Err 149 } else { 150 members := result.Data.([]*model.TeamMember) 151 for _, m := range members { 152 if m.TeamId == teamId { 153 member = m 154 } 155 } 156 } 157 158 if member == nil { 159 err := model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId, http.StatusBadRequest) 160 return nil, err 161 } 162 163 if err := a.CheckRolesExist(strings.Fields(newRoles)); err != nil { 164 return nil, err 165 } 166 167 member.Roles = newRoles 168 169 if result := <-a.Srv.Store.Team().UpdateMember(member); result.Err != nil { 170 return nil, result.Err 171 } 172 173 a.ClearSessionCacheForUser(userId) 174 175 a.sendUpdatedMemberRoleEvent(userId, member) 176 177 return member, nil 178 } 179 180 func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) { 181 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil) 182 message.Add("member", member.ToJson()) 183 a.Publish(message) 184 } 185 186 func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) { 187 tchan := a.Srv.Store.Team().Get(teamId) 188 uchan := a.Srv.Store.User().Get(userId) 189 190 var team *model.Team 191 if result := <-tchan; result.Err != nil { 192 return nil, result.Err 193 } else { 194 team = result.Data.(*model.Team) 195 } 196 197 var user *model.User 198 if result := <-uchan; result.Err != nil { 199 return nil, result.Err 200 } else { 201 user = result.Data.(*model.User) 202 } 203 204 if err := a.JoinUserToTeam(team, user, userRequestorId); err != nil { 205 return nil, err 206 } 207 208 return team, nil 209 } 210 211 func (a *App) AddUserToTeamByTeamId(teamId string, user *model.User) *model.AppError { 212 if result := <-a.Srv.Store.Team().Get(teamId); result.Err != nil { 213 return result.Err 214 } else { 215 return a.JoinUserToTeam(result.Data.(*model.Team), user, "") 216 } 217 } 218 219 func (a *App) AddUserToTeamByToken(userId string, tokenId string) (*model.Team, *model.AppError) { 220 result := <-a.Srv.Store.Token().GetByToken(tokenId) 221 if result.Err != nil { 222 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, result.Err.Error(), http.StatusBadRequest) 223 } 224 225 token := result.Data.(*model.Token) 226 if token.Type != TOKEN_TYPE_TEAM_INVITATION { 227 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest) 228 } 229 230 if model.GetMillis()-token.CreateAt >= TEAM_INVITATION_EXPIRY_TIME { 231 a.DeleteToken(token) 232 return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest) 233 } 234 235 tokenData := model.MapFromJson(strings.NewReader(token.Extra)) 236 237 tchan := a.Srv.Store.Team().Get(tokenData["teamId"]) 238 uchan := a.Srv.Store.User().Get(userId) 239 240 var team *model.Team 241 if result := <-tchan; result.Err != nil { 242 return nil, result.Err 243 } else { 244 team = result.Data.(*model.Team) 245 } 246 247 var user *model.User 248 if result := <-uchan; result.Err != nil { 249 return nil, result.Err 250 } else { 251 user = result.Data.(*model.User) 252 } 253 254 if err := a.JoinUserToTeam(team, user, ""); err != nil { 255 return nil, err 256 } 257 258 if err := a.DeleteToken(token); err != nil { 259 return nil, err 260 } 261 262 return team, nil 263 } 264 265 func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) { 266 tchan := a.Srv.Store.Team().GetByInviteId(inviteId) 267 uchan := a.Srv.Store.User().Get(userId) 268 269 var team *model.Team 270 if result := <-tchan; result.Err != nil { 271 return nil, result.Err 272 } else { 273 team = result.Data.(*model.Team) 274 } 275 276 var user *model.User 277 if result := <-uchan; result.Err != nil { 278 return nil, result.Err 279 } else { 280 user = result.Data.(*model.User) 281 } 282 283 if err := a.JoinUserToTeam(team, user, ""); err != nil { 284 return nil, err 285 } 286 287 return team, nil 288 } 289 290 // Returns three values: 291 // 1. a pointer to the team member, if successful 292 // 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false. 293 // 3. a pointer to an AppError if something went wrong. 294 func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) { 295 tm := &model.TeamMember{ 296 TeamId: team.Id, 297 UserId: user.Id, 298 Roles: model.TEAM_USER_ROLE_ID, 299 } 300 301 if team.Email == user.Email { 302 tm.Roles = model.TEAM_USER_ROLE_ID + " " + model.TEAM_ADMIN_ROLE_ID 303 } 304 305 if etmr := <-a.Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil { 306 // Membership already exists. Check if deleted and and update, otherwise do nothing 307 rtm := etmr.Data.(*model.TeamMember) 308 309 // Do nothing if already added 310 if rtm.DeleteAt == 0 { 311 return rtm, true, nil 312 } 313 314 if membersCount := <-a.Srv.Store.Team().GetActiveMemberCount(tm.TeamId); membersCount.Err != nil { 315 return nil, false, membersCount.Err 316 } else if membersCount.Data.(int64) >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) { 317 return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest) 318 } else { 319 if tmr := <-a.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil { 320 return nil, false, tmr.Err 321 } else { 322 return tmr.Data.(*model.TeamMember), false, nil 323 } 324 } 325 } else { 326 // Membership appears to be missing. Lets try to add. 327 if tmr := <-a.Srv.Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam); tmr.Err != nil { 328 return nil, false, tmr.Err 329 } else { 330 return tmr.Data.(*model.TeamMember), false, nil 331 } 332 } 333 } 334 335 func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError { 336 if _, alreadyAdded, err := a.joinUserToTeam(team, user); err != nil { 337 return err 338 } else if alreadyAdded { 339 return nil 340 } 341 342 if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil { 343 return uua.Err 344 } 345 346 channelRole := model.CHANNEL_USER_ROLE_ID 347 348 if team.Email == user.Email { 349 channelRole = model.CHANNEL_USER_ROLE_ID + " " + model.CHANNEL_ADMIN_ROLE_ID 350 } 351 352 // Soft error if there is an issue joining the default channels 353 if err := a.JoinDefaultChannels(team.Id, user, channelRole, userRequestorId); err != nil { 354 mlog.Error(fmt.Sprintf("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", user.Id, team.Id, err), mlog.String("user_id", user.Id)) 355 } 356 357 a.ClearSessionCacheForUser(user.Id) 358 a.InvalidateCacheForUser(user.Id) 359 360 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil) 361 message.Add("team_id", team.Id) 362 message.Add("user_id", user.Id) 363 a.Publish(message) 364 365 return nil 366 } 367 368 func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) { 369 if result := <-a.Srv.Store.Team().Get(teamId); result.Err != nil { 370 return nil, result.Err 371 } else { 372 return result.Data.(*model.Team), nil 373 } 374 } 375 376 func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) { 377 if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil { 378 result.Err.StatusCode = http.StatusNotFound 379 return nil, result.Err 380 } else { 381 return result.Data.(*model.Team), nil 382 } 383 } 384 385 func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) { 386 if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil { 387 return nil, result.Err 388 } else { 389 return result.Data.(*model.Team), nil 390 } 391 } 392 393 func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) { 394 if result := <-a.Srv.Store.Team().GetAll(); result.Err != nil { 395 return nil, result.Err 396 } else { 397 return result.Data.([]*model.Team), nil 398 } 399 } 400 401 func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) { 402 if result := <-a.Srv.Store.Team().GetAllPage(offset, limit); result.Err != nil { 403 return nil, result.Err 404 } else { 405 return result.Data.([]*model.Team), nil 406 } 407 } 408 409 func (a *App) GetAllOpenTeams() ([]*model.Team, *model.AppError) { 410 if result := <-a.Srv.Store.Team().GetAllTeamListing(); result.Err != nil { 411 return nil, result.Err 412 } else { 413 return result.Data.([]*model.Team), nil 414 } 415 } 416 417 func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) { 418 if result := <-a.Srv.Store.Team().SearchAll(term); result.Err != nil { 419 return nil, result.Err 420 } else { 421 return result.Data.([]*model.Team), nil 422 } 423 } 424 425 func (a *App) SearchOpenTeams(term string) ([]*model.Team, *model.AppError) { 426 if result := <-a.Srv.Store.Team().SearchOpen(term); result.Err != nil { 427 return nil, result.Err 428 } else { 429 return result.Data.([]*model.Team), nil 430 } 431 } 432 433 func (a *App) GetAllOpenTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) { 434 if result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit); result.Err != nil { 435 return nil, result.Err 436 } else { 437 return result.Data.([]*model.Team), nil 438 } 439 } 440 441 func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) { 442 if result := <-a.Srv.Store.Team().GetTeamsByUserId(userId); result.Err != nil { 443 return nil, result.Err 444 } else { 445 return result.Data.([]*model.Team), nil 446 } 447 } 448 449 func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { 450 if result := <-a.Srv.Store.Team().GetMember(teamId, userId); result.Err != nil { 451 return nil, result.Err 452 } else { 453 return result.Data.(*model.TeamMember), nil 454 } 455 } 456 457 func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) { 458 if result := <-a.Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil { 459 return nil, result.Err 460 } else { 461 return result.Data.([]*model.TeamMember), nil 462 } 463 } 464 465 func (a *App) GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) { 466 if result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit); result.Err != nil { 467 return nil, result.Err 468 } else { 469 return result.Data.([]*model.TeamMember), nil 470 } 471 } 472 473 func (a *App) GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) { 474 if result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds); result.Err != nil { 475 return nil, result.Err 476 } else { 477 return result.Data.([]*model.TeamMember), nil 478 } 479 } 480 481 func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { 482 if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil { 483 return nil, err 484 } 485 486 var teamMember *model.TeamMember 487 var err *model.AppError 488 if teamMember, err = a.GetTeamMember(teamId, userId); err != nil { 489 return nil, err 490 } 491 492 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil) 493 message.Add("team_id", teamId) 494 message.Add("user_id", userId) 495 a.Publish(message) 496 497 return teamMember, nil 498 } 499 500 func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string) ([]*model.TeamMember, *model.AppError) { 501 var members []*model.TeamMember 502 503 for _, userId := range userIds { 504 if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil { 505 return nil, err 506 } 507 508 if teamMember, err := a.GetTeamMember(teamId, userId); err != nil { 509 return nil, err 510 } else { 511 members = append(members, teamMember) 512 } 513 514 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil) 515 message.Add("team_id", teamId) 516 message.Add("user_id", userId) 517 a.Publish(message) 518 } 519 520 return members, nil 521 } 522 523 func (a *App) AddTeamMemberByToken(userId, tokenId string) (*model.TeamMember, *model.AppError) { 524 var team *model.Team 525 var err *model.AppError 526 527 if team, err = a.AddUserToTeamByToken(userId, tokenId); err != nil { 528 return nil, err 529 } 530 531 if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil { 532 return nil, err 533 } else { 534 return teamMember, nil 535 } 536 } 537 538 func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) { 539 var team *model.Team 540 var err *model.AppError 541 542 if team, err = a.AddUserToTeamByInviteId(inviteId, userId); err != nil { 543 return nil, err 544 } 545 546 if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil { 547 return nil, err 548 } else { 549 return teamMember, nil 550 } 551 } 552 553 func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) { 554 result := <-a.Srv.Store.Team().GetChannelUnreadsForTeam(teamId, userId) 555 if result.Err != nil { 556 return nil, result.Err 557 } 558 559 channelUnreads := result.Data.([]*model.ChannelUnread) 560 var teamUnread = &model.TeamUnread{ 561 MsgCount: 0, 562 MentionCount: 0, 563 TeamId: teamId, 564 } 565 566 for _, cu := range channelUnreads { 567 teamUnread.MentionCount += cu.MentionCount 568 569 if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION { 570 teamUnread.MsgCount += cu.MsgCount 571 } 572 } 573 574 return teamUnread, nil 575 } 576 577 func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError { 578 tchan := a.Srv.Store.Team().Get(teamId) 579 uchan := a.Srv.Store.User().Get(userId) 580 581 var team *model.Team 582 if result := <-tchan; result.Err != nil { 583 return result.Err 584 } else { 585 team = result.Data.(*model.Team) 586 } 587 588 var user *model.User 589 if result := <-uchan; result.Err != nil { 590 return result.Err 591 } else { 592 user = result.Data.(*model.User) 593 } 594 595 if err := a.LeaveTeam(team, user, requestorId); err != nil { 596 return err 597 } 598 599 return nil 600 } 601 602 func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError { 603 var teamMember *model.TeamMember 604 var err *model.AppError 605 606 if teamMember, err = a.GetTeamMember(team.Id, user.Id); err != nil { 607 return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest) 608 } 609 610 var channelList *model.ChannelList 611 612 if result := <-a.Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil { 613 if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" { 614 channelList = &model.ChannelList{} 615 } else { 616 return result.Err 617 } 618 619 } else { 620 channelList = result.Data.(*model.ChannelList) 621 } 622 623 for _, channel := range *channelList { 624 if !channel.IsGroupOrDirect() { 625 a.InvalidateCacheForChannelMembers(channel.Id) 626 if result := <-a.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil { 627 return result.Err 628 } 629 } 630 } 631 632 var channel *model.Channel 633 if result := <-a.Srv.Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false); result.Err != nil { 634 return result.Err 635 } else { 636 channel = result.Data.(*model.Channel) 637 } 638 639 if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 640 if requestorId == user.Id { 641 if err := a.postLeaveTeamMessage(user, channel); err != nil { 642 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 643 } 644 } else { 645 if err := a.postRemoveFromTeamMessage(user, channel); err != nil { 646 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 647 } 648 } 649 } 650 651 // Send the websocket message before we actually do the remove so the user being removed gets it. 652 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil) 653 message.Add("user_id", user.Id) 654 message.Add("team_id", team.Id) 655 a.Publish(message) 656 657 teamMember.Roles = "" 658 teamMember.DeleteAt = model.GetMillis() 659 660 if result := <-a.Srv.Store.Team().UpdateMember(teamMember); result.Err != nil { 661 return result.Err 662 } 663 664 if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil { 665 return uua.Err 666 } 667 668 // delete the preferences that set the last channel used in the team and other team specific preferences 669 if result := <-a.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil { 670 return result.Err 671 } 672 673 a.ClearSessionCacheForUser(user.Id) 674 a.InvalidateCacheForUser(user.Id) 675 676 return nil 677 } 678 679 func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 680 post := &model.Post{ 681 ChannelId: channel.Id, 682 Message: fmt.Sprintf(utils.T("api.team.leave.left"), user.Username), 683 Type: model.POST_LEAVE_TEAM, 684 UserId: user.Id, 685 Props: model.StringInterface{ 686 "username": user.Username, 687 }, 688 } 689 690 if _, err := a.CreatePost(post, channel, false); err != nil { 691 return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 692 } 693 694 return nil 695 } 696 697 func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 698 post := &model.Post{ 699 ChannelId: channel.Id, 700 Message: fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username), 701 Type: model.POST_REMOVE_FROM_TEAM, 702 UserId: user.Id, 703 Props: model.StringInterface{ 704 "username": user.Username, 705 }, 706 } 707 708 if _, err := a.CreatePost(post, channel, false); err != nil { 709 return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 710 } 711 712 return nil 713 } 714 715 func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError { 716 if len(emailList) == 0 { 717 err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest) 718 return err 719 } 720 721 var invalidEmailList []string 722 723 for _, email := range emailList { 724 if !a.isTeamEmailAddressAllowed(email) { 725 invalidEmailList = append(invalidEmailList, email) 726 } 727 } 728 729 if len(invalidEmailList) > 0 { 730 s := strings.Join(invalidEmailList, ", ") 731 err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest) 732 return err 733 } 734 735 tchan := a.Srv.Store.Team().Get(teamId) 736 uchan := a.Srv.Store.User().Get(senderId) 737 738 var team *model.Team 739 if result := <-tchan; result.Err != nil { 740 return result.Err 741 } else { 742 team = result.Data.(*model.Team) 743 } 744 745 var user *model.User 746 if result := <-uchan; result.Err != nil { 747 return result.Err 748 } else { 749 user = result.Data.(*model.User) 750 } 751 752 nameFormat := *a.Config().TeamSettings.TeammateNameDisplay 753 a.SendInviteEmails(team, user.GetDisplayName(nameFormat), emailList, a.GetSiteURL()) 754 755 return nil 756 } 757 758 func (a *App) FindTeamByName(name string) bool { 759 if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil { 760 return false 761 } else { 762 return true 763 } 764 } 765 766 func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) { 767 if result := <-a.Srv.Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId); result.Err != nil { 768 return nil, result.Err 769 } else { 770 data := result.Data.([]*model.ChannelUnread) 771 members := []*model.TeamUnread{} 772 membersMap := make(map[string]*model.TeamUnread) 773 774 unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread { 775 tu.MentionCount += cu.MentionCount 776 777 if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION { 778 tu.MsgCount += cu.MsgCount 779 } 780 781 return tu 782 } 783 784 for i := range data { 785 id := data[i].TeamId 786 if mu, ok := membersMap[id]; ok { 787 membersMap[id] = unreads(data[i], mu) 788 } else { 789 membersMap[id] = unreads(data[i], &model.TeamUnread{ 790 MsgCount: 0, 791 MentionCount: 0, 792 TeamId: id, 793 }) 794 } 795 } 796 797 for _, val := range membersMap { 798 members = append(members, val) 799 } 800 801 return members, nil 802 } 803 } 804 805 func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError { 806 team, err := a.GetTeam(teamId) 807 if err != nil { 808 return err 809 } 810 811 return a.PermanentDeleteTeam(team) 812 } 813 814 func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError { 815 team.DeleteAt = model.GetMillis() 816 if result := <-a.Srv.Store.Team().Update(team); result.Err != nil { 817 return result.Err 818 } 819 820 if result := <-a.Srv.Store.Channel().GetTeamChannels(team.Id); result.Err != nil { 821 if result.Err.Id != "store.sql_channel.get_channels.not_found.app_error" { 822 return result.Err 823 } 824 } else { 825 channels := result.Data.(*model.ChannelList) 826 for _, c := range *channels { 827 a.PermanentDeleteChannel(c) 828 } 829 } 830 831 if result := <-a.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil { 832 return result.Err 833 } 834 835 if result := <-a.Srv.Store.Command().PermanentDeleteByTeam(team.Id); result.Err != nil { 836 return result.Err 837 } 838 839 if result := <-a.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil { 840 return result.Err 841 } 842 843 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM) 844 845 return nil 846 } 847 848 func (a *App) SoftDeleteTeam(teamId string) *model.AppError { 849 team, err := a.GetTeam(teamId) 850 if err != nil { 851 return err 852 } 853 854 team.DeleteAt = model.GetMillis() 855 if result := <-a.Srv.Store.Team().Update(team); result.Err != nil { 856 return result.Err 857 } 858 859 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM) 860 861 return nil 862 } 863 864 func (a *App) GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) { 865 tchan := a.Srv.Store.Team().GetTotalMemberCount(teamId) 866 achan := a.Srv.Store.Team().GetActiveMemberCount(teamId) 867 868 stats := &model.TeamStats{} 869 stats.TeamId = teamId 870 871 if result := <-tchan; result.Err != nil { 872 return nil, result.Err 873 } else { 874 stats.TotalMemberCount = result.Data.(int64) 875 } 876 877 if result := <-achan; result.Err != nil { 878 return nil, result.Err 879 } else { 880 stats.ActiveMemberCount = result.Data.(int64) 881 } 882 883 return stats, nil 884 } 885 886 func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) { 887 tokenId := query.Get("t") 888 inviteId := query.Get("id") 889 890 if len(tokenId) > 0 { 891 result := <-a.Srv.Store.Token().GetByToken(tokenId) 892 if result.Err != nil { 893 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest) 894 } 895 896 token := result.Data.(*model.Token) 897 if token.Type != TOKEN_TYPE_TEAM_INVITATION { 898 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest) 899 } 900 901 if model.GetMillis()-token.CreateAt >= TEAM_INVITATION_EXPIRY_TIME { 902 a.DeleteToken(token) 903 return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest) 904 } 905 906 tokenData := model.MapFromJson(strings.NewReader(token.Extra)) 907 908 return tokenData["teamId"], nil 909 } else if len(inviteId) > 0 { 910 if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil { 911 // soft fail, so we still create user but don't auto-join team 912 mlog.Error(fmt.Sprintf("%v", result.Err)) 913 } else { 914 return result.Data.(*model.Team).Id, nil 915 } 916 } 917 918 return "", nil 919 } 920 921 func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team { 922 if !a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) { 923 team.Sanitize() 924 } 925 926 return team 927 } 928 929 func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team { 930 for _, team := range teams { 931 a.SanitizeTeam(session, team) 932 } 933 934 return teams 935 } 936 937 func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) { 938 if len(*a.Config().FileSettings.DriverName) == 0 { 939 return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented) 940 } else { 941 path := "teams/" + team.Id + "/teamIcon.png" 942 if data, err := a.ReadFile(path); err != nil { 943 return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound) 944 } else { 945 return data, nil 946 } 947 } 948 } 949 950 func (a *App) SetTeamIcon(teamId string, imageData *multipart.FileHeader) *model.AppError { 951 file, err := imageData.Open() 952 if err != nil { 953 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest) 954 } 955 defer file.Close() 956 return a.SetTeamIconFromFile(teamId, file) 957 } 958 959 func (a *App) SetTeamIconFromFile(teamId string, file multipart.File) *model.AppError { 960 961 team, getTeamErr := a.GetTeam(teamId) 962 963 if getTeamErr != nil { 964 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest) 965 } 966 967 if len(*a.Config().FileSettings.DriverName) == 0 { 968 return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented) 969 } 970 971 // Decode image config first to check dimensions before loading the whole thing into memory later on 972 config, _, err := image.DecodeConfig(file) 973 if err != nil { 974 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode_config.app_error", nil, err.Error(), http.StatusBadRequest) 975 } else if config.Width*config.Height > model.MaxImageSize { 976 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, err.Error(), http.StatusBadRequest) 977 } 978 979 file.Seek(0, 0) 980 981 // Decode image into Image object 982 img, _, err := image.Decode(file) 983 if err != nil { 984 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest) 985 } 986 987 file.Seek(0, 0) 988 989 orientation, _ := getImageOrientation(file) 990 img = makeImageUpright(img, orientation) 991 992 // Scale team icon 993 teamIconWidthAndHeight := 128 994 img = imaging.Fill(img, teamIconWidthAndHeight, teamIconWidthAndHeight, imaging.Center, imaging.Lanczos) 995 996 buf := new(bytes.Buffer) 997 err = png.Encode(buf, img) 998 if err != nil { 999 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError) 1000 } 1001 1002 path := "teams/" + teamId + "/teamIcon.png" 1003 1004 if err := a.WriteFile(buf.Bytes(), path); err != nil { 1005 return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, "", http.StatusInternalServerError) 1006 } 1007 1008 curTime := model.GetMillis() 1009 1010 if result := <-a.Srv.Store.Team().UpdateLastTeamIconUpdate(teamId, curTime); result.Err != nil { 1011 return model.NewAppError("SetTeamIcon", "api.team.team_icon.update.app_error", nil, result.Err.Error(), http.StatusBadRequest) 1012 } 1013 1014 // manually set time to avoid possible cluster inconsistencies 1015 team.LastTeamIconUpdate = curTime 1016 1017 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM) 1018 1019 return nil 1020 } 1021 1022 func (a *App) RemoveTeamIcon(teamId string) *model.AppError { 1023 team, err := a.GetTeam(teamId) 1024 if err != nil { 1025 return model.NewAppError("RemoveTeamIcon", "api.team.remove_team_icon.get_team.app_error", nil, err.Error(), http.StatusBadRequest) 1026 } 1027 1028 if result := <-a.Srv.Store.Team().UpdateLastTeamIconUpdate(teamId, 0); result.Err != nil { 1029 return model.NewAppError("RemoveTeamIcon", "api.team.team_icon.update.app_error", nil, result.Err.Error(), http.StatusBadRequest) 1030 } 1031 1032 team.LastTeamIconUpdate = 0 1033 1034 a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM) 1035 1036 return nil 1037 }