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