github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+incompatible/app/channel.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 "fmt" 8 "net/http" 9 "strings" 10 "time" 11 12 "github.com/mattermost/mattermost-server/mlog" 13 "github.com/mattermost/mattermost-server/model" 14 "github.com/mattermost/mattermost-server/plugin" 15 "github.com/mattermost/mattermost-server/store" 16 "github.com/mattermost/mattermost-server/utils" 17 ) 18 19 func (a *App) CreateDefaultChannels(teamId string) ([]*model.Channel, *model.AppError) { 20 townSquare := &model.Channel{DisplayName: utils.T("api.channel.create_default_channels.town_square"), Name: "town-square", Type: model.CHANNEL_OPEN, TeamId: teamId} 21 22 if _, err := a.CreateChannel(townSquare, false); err != nil { 23 return nil, err 24 } 25 26 offTopic := &model.Channel{DisplayName: utils.T("api.channel.create_default_channels.off_topic"), Name: "off-topic", Type: model.CHANNEL_OPEN, TeamId: teamId} 27 28 if _, err := a.CreateChannel(offTopic, false); err != nil { 29 return nil, err 30 } 31 32 channels := []*model.Channel{townSquare, offTopic} 33 return channels, nil 34 } 35 36 func (a *App) JoinDefaultChannels(teamId string, user *model.User, shouldBeAdmin bool, userRequestorId string) *model.AppError { 37 var err *model.AppError = nil 38 39 var requestor *model.User 40 if userRequestorId != "" { 41 u := <-a.Srv.Store.User().Get(userRequestorId) 42 if u.Err != nil { 43 return u.Err 44 } 45 requestor = u.Data.(*model.User) 46 } 47 48 defaultChannelList := []string{"town-square"} 49 50 if len(a.Config().TeamSettings.ExperimentalDefaultChannels) == 0 { 51 defaultChannelList = append(defaultChannelList, "off-topic") 52 } else { 53 seenChannels := map[string]bool{} 54 for _, channelName := range a.Config().TeamSettings.ExperimentalDefaultChannels { 55 if !seenChannels[channelName] { 56 defaultChannelList = append(defaultChannelList, channelName) 57 seenChannels[channelName] = true 58 } 59 } 60 } 61 62 for _, channelName := range defaultChannelList { 63 if result := <-a.Srv.Store.Channel().GetByName(teamId, channelName, true); result.Err != nil { 64 err = result.Err 65 } else { 66 67 channel := result.Data.(*model.Channel) 68 69 if channel.Type != model.CHANNEL_OPEN { 70 continue 71 } 72 73 cm := &model.ChannelMember{ 74 ChannelId: channel.Id, 75 UserId: user.Id, 76 SchemeUser: true, 77 SchemeAdmin: shouldBeAdmin, 78 NotifyProps: model.GetDefaultChannelNotifyProps(), 79 } 80 81 if cmResult := <-a.Srv.Store.Channel().SaveMember(cm); cmResult.Err != nil { 82 err = cmResult.Err 83 } 84 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { 85 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 86 } 87 88 if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 89 if channel.Name == model.DEFAULT_CHANNEL { 90 if requestor == nil { 91 if err := a.postJoinTeamMessage(user, channel); err != nil { 92 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 93 } 94 } else { 95 if err := a.postAddToTeamMessage(requestor, user, channel, ""); err != nil { 96 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 97 } 98 } 99 } else { 100 if requestor == nil { 101 if err := a.postJoinChannelMessage(user, channel); err != nil { 102 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 103 } 104 } else { 105 if err := a.PostAddToChannelMessage(requestor, user, channel, ""); err != nil { 106 mlog.Error(fmt.Sprint("Failed to post join/leave message", err)) 107 } 108 } 109 } 110 } 111 112 a.InvalidateCacheForChannelMembers(result.Data.(*model.Channel).Id) 113 } 114 } 115 116 return err 117 } 118 119 func (a *App) CreateChannelWithUser(channel *model.Channel, userId string) (*model.Channel, *model.AppError) { 120 if channel.IsGroupOrDirect() { 121 return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.direct_channel.app_error", nil, "", http.StatusBadRequest) 122 } 123 124 if strings.Index(channel.Name, "__") > 0 { 125 return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.invalid_character.app_error", nil, "", http.StatusBadRequest) 126 } 127 128 if len(channel.TeamId) == 0 { 129 return nil, model.NewAppError("CreateChannelWithUser", "app.channel.create_channel.no_team_id.app_error", nil, "", http.StatusBadRequest) 130 } 131 132 // Get total number of channels on current team 133 count, err := a.GetNumberOfChannelsOnTeam(channel.TeamId) 134 if err != nil { 135 return nil, err 136 } 137 138 if int64(count+1) > *a.Config().TeamSettings.MaxChannelsPerTeam { 139 return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.max_channel_limit.app_error", map[string]interface{}{"MaxChannelsPerTeam": *a.Config().TeamSettings.MaxChannelsPerTeam}, "", http.StatusBadRequest) 140 } 141 142 channel.CreatorId = userId 143 144 rchannel, err := a.CreateChannel(channel, true) 145 if err != nil { 146 return nil, err 147 } 148 149 var user *model.User 150 if user, err = a.GetUser(userId); err != nil { 151 return nil, err 152 } 153 154 a.postJoinChannelMessage(user, channel) 155 156 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CREATED, "", "", userId, nil) 157 message.Add("channel_id", channel.Id) 158 message.Add("team_id", channel.TeamId) 159 a.Publish(message) 160 161 return rchannel, nil 162 } 163 164 // RenameChannel is used to rename the channel Name and the DisplayName fields 165 func (a *App) RenameChannel(channel *model.Channel, newChannelName string, newDisplayName string) (*model.Channel, *model.AppError) { 166 if channel.Type == model.CHANNEL_DIRECT { 167 return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_direct_messages.app_error", nil, "", http.StatusBadRequest) 168 } 169 170 if channel.Type == model.CHANNEL_GROUP { 171 return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_group_messages.app_error", nil, "", http.StatusBadRequest) 172 } 173 174 channel.Name = newChannelName 175 if newDisplayName != "" { 176 channel.DisplayName = newDisplayName 177 } 178 179 newChannel, err := a.UpdateChannel(channel) 180 if err != nil { 181 return nil, err 182 } 183 184 return newChannel, nil 185 } 186 187 func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) { 188 result := <-a.Srv.Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam) 189 if result.Err != nil { 190 return nil, result.Err 191 } 192 193 sc := result.Data.(*model.Channel) 194 195 if addMember { 196 cm := &model.ChannelMember{ 197 ChannelId: sc.Id, 198 UserId: channel.CreatorId, 199 SchemeUser: true, 200 SchemeAdmin: true, 201 NotifyProps: model.GetDefaultChannelNotifyProps(), 202 } 203 204 if cmresult := <-a.Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil { 205 return nil, cmresult.Err 206 } 207 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(channel.CreatorId, sc.Id, model.GetMillis()); result.Err != nil { 208 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 209 } 210 211 a.InvalidateCacheForUser(channel.CreatorId) 212 } 213 214 if a.PluginsReady() { 215 a.Go(func() { 216 pluginContext := &plugin.Context{} 217 a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 218 hooks.ChannelHasBeenCreated(pluginContext, sc) 219 return true 220 }, plugin.ChannelHasBeenCreatedId) 221 }) 222 } 223 224 return sc, nil 225 } 226 227 func (a *App) CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { 228 channel, err := a.createDirectChannel(userId, otherUserId) 229 if err != nil { 230 if err.Id == store.CHANNEL_EXISTS_ERROR { 231 return channel, nil 232 } 233 return nil, err 234 } 235 236 a.WaitForChannelMembership(channel.Id, userId) 237 238 a.InvalidateCacheForUser(userId) 239 a.InvalidateCacheForUser(otherUserId) 240 241 if a.PluginsReady() { 242 a.Go(func() { 243 pluginContext := &plugin.Context{} 244 a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 245 hooks.ChannelHasBeenCreated(pluginContext, channel) 246 return true 247 }, plugin.ChannelHasBeenCreatedId) 248 }) 249 } 250 251 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) 252 message.Add("teammate_id", otherUserId) 253 a.Publish(message) 254 255 return channel, nil 256 } 257 258 func (a *App) createDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { 259 uc1 := a.Srv.Store.User().Get(userId) 260 uc2 := a.Srv.Store.User().Get(otherUserId) 261 262 if result := <-uc1; result.Err != nil { 263 return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, userId, http.StatusBadRequest) 264 } 265 266 if result := <-uc2; result.Err != nil { 267 return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId, http.StatusBadRequest) 268 } 269 270 result := <-a.Srv.Store.Channel().CreateDirectChannel(userId, otherUserId) 271 if result.Err != nil { 272 if result.Err.Id == store.CHANNEL_EXISTS_ERROR { 273 return result.Data.(*model.Channel), result.Err 274 } 275 return nil, result.Err 276 } 277 278 channel := result.Data.(*model.Channel) 279 280 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId, channel.Id, model.GetMillis()); result.Err != nil { 281 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 282 } 283 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(otherUserId, channel.Id, model.GetMillis()); result.Err != nil { 284 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 285 } 286 287 return channel, nil 288 } 289 290 func (a *App) WaitForChannelMembership(channelId string, userId string) { 291 if len(a.Config().SqlSettings.DataSourceReplicas) == 0 { 292 return 293 } 294 295 now := model.GetMillis() 296 297 for model.GetMillis()-now < 12000 { 298 299 time.Sleep(100 * time.Millisecond) 300 301 result := <-a.Srv.Store.Channel().GetMember(channelId, userId) 302 303 // If the membership was found then return 304 if result.Err == nil { 305 return 306 } 307 308 // If we received a error but it wasn't a missing channel member then return 309 if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 310 return 311 } 312 } 313 314 mlog.Error(fmt.Sprintf("WaitForChannelMembership giving up channelId=%v userId=%v", channelId, userId), mlog.String("user_id", userId)) 315 } 316 317 func (a *App) CreateGroupChannel(userIds []string, creatorId string) (*model.Channel, *model.AppError) { 318 channel, err := a.createGroupChannel(userIds, creatorId) 319 if err != nil { 320 if err.Id == store.CHANNEL_EXISTS_ERROR { 321 return channel, nil 322 } 323 return nil, err 324 } 325 326 for _, userId := range userIds { 327 if userId == creatorId { 328 a.WaitForChannelMembership(channel.Id, creatorId) 329 } 330 331 a.InvalidateCacheForUser(userId) 332 } 333 334 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_GROUP_ADDED, "", channel.Id, "", nil) 335 message.Add("teammate_ids", model.ArrayToJson(userIds)) 336 a.Publish(message) 337 338 return channel, nil 339 } 340 341 func (a *App) createGroupChannel(userIds []string, creatorId string) (*model.Channel, *model.AppError) { 342 if len(userIds) > model.CHANNEL_GROUP_MAX_USERS || len(userIds) < model.CHANNEL_GROUP_MIN_USERS { 343 return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) 344 } 345 346 result := <-a.Srv.Store.User().GetProfileByIds(userIds, true) 347 if result.Err != nil { 348 return nil, result.Err 349 } 350 users := result.Data.([]*model.User) 351 352 if len(users) != len(userIds) { 353 return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIds), http.StatusBadRequest) 354 } 355 356 group := &model.Channel{ 357 Name: model.GetGroupNameFromUserIds(userIds), 358 DisplayName: model.GetGroupDisplayNameFromUsers(users, true), 359 Type: model.CHANNEL_GROUP, 360 } 361 362 result = <-a.Srv.Store.Channel().Save(group, *a.Config().TeamSettings.MaxChannelsPerTeam) 363 if result.Err != nil { 364 if result.Err.Id == store.CHANNEL_EXISTS_ERROR { 365 return result.Data.(*model.Channel), result.Err 366 } 367 return nil, result.Err 368 } 369 channel := result.Data.(*model.Channel) 370 371 for _, user := range users { 372 cm := &model.ChannelMember{ 373 UserId: user.Id, 374 ChannelId: group.Id, 375 NotifyProps: model.GetDefaultChannelNotifyProps(), 376 SchemeUser: true, 377 } 378 379 if result := <-a.Srv.Store.Channel().SaveMember(cm); result.Err != nil { 380 return nil, result.Err 381 } 382 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { 383 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 384 } 385 } 386 387 return channel, nil 388 } 389 390 func (a *App) GetGroupChannel(userIds []string) (*model.Channel, *model.AppError) { 391 if len(userIds) > model.CHANNEL_GROUP_MAX_USERS || len(userIds) < model.CHANNEL_GROUP_MIN_USERS { 392 return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) 393 } 394 395 result := <-a.Srv.Store.User().GetProfileByIds(userIds, true) 396 if result.Err != nil { 397 return nil, result.Err 398 } 399 users := result.Data.([]*model.User) 400 401 if len(users) != len(userIds) { 402 return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIds), http.StatusBadRequest) 403 } 404 405 channel, err := a.GetChannelByName(model.GetGroupNameFromUserIds(userIds), "", true) 406 if err != nil { 407 return nil, err 408 } 409 410 return channel, nil 411 } 412 413 func (a *App) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { 414 result := <-a.Srv.Store.Channel().Update(channel) 415 if result.Err != nil { 416 return nil, result.Err 417 } 418 419 a.InvalidateCacheForChannel(channel) 420 421 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_UPDATED, "", channel.Id, "", nil) 422 messageWs.Add("channel", channel.ToJson()) 423 a.Publish(messageWs) 424 425 return channel, nil 426 } 427 428 func (a *App) UpdateChannelScheme(channel *model.Channel) (*model.Channel, *model.AppError) { 429 var oldChannel *model.Channel 430 var err *model.AppError 431 if oldChannel, err = a.GetChannel(channel.Id); err != nil { 432 return nil, err 433 } 434 435 oldChannel.SchemeId = channel.SchemeId 436 437 newChannel, err := a.UpdateChannel(oldChannel) 438 if err != nil { 439 return nil, err 440 } 441 442 return newChannel, nil 443 } 444 445 func (a *App) UpdateChannelPrivacy(oldChannel *model.Channel, user *model.User) (*model.Channel, *model.AppError) { 446 channel, err := a.UpdateChannel(oldChannel) 447 if err != nil { 448 return channel, err 449 } 450 451 if err := a.postChannelPrivacyMessage(user, channel); err != nil { 452 if channel.Type == model.CHANNEL_OPEN { 453 channel.Type = model.CHANNEL_PRIVATE 454 } else { 455 channel.Type = model.CHANNEL_OPEN 456 } 457 // revert to previous channel privacy 458 a.UpdateChannel(channel) 459 return channel, err 460 } 461 462 a.InvalidateCacheForChannel(channel) 463 464 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CONVERTED, channel.TeamId, "", "", nil) 465 messageWs.Add("channel_id", channel.Id) 466 a.Publish(messageWs) 467 468 return channel, nil 469 } 470 471 func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel) *model.AppError { 472 message := (map[string]string{ 473 model.CHANNEL_OPEN: utils.T("api.channel.change_channel_privacy.private_to_public"), 474 model.CHANNEL_PRIVATE: utils.T("api.channel.change_channel_privacy.public_to_private"), 475 })[channel.Type] 476 post := &model.Post{ 477 ChannelId: channel.Id, 478 Message: message, 479 Type: model.POST_CHANGE_CHANNEL_PRIVACY, 480 UserId: user.Id, 481 Props: model.StringInterface{ 482 "username": user.Username, 483 }, 484 } 485 486 if _, err := a.CreatePost(post, channel, false); err != nil { 487 return model.NewAppError("postChannelPrivacyMessage", "api.channel.post_channel_privacy_message.error", nil, err.Error(), http.StatusInternalServerError) 488 } 489 490 return nil 491 } 492 493 func (a *App) RestoreChannel(channel *model.Channel) (*model.Channel, *model.AppError) { 494 result := <-a.Srv.Store.Channel().Restore(channel.Id, model.GetMillis()) 495 if result.Err != nil { 496 return nil, result.Err 497 } 498 return channel, nil 499 } 500 501 func (a *App) PatchChannel(channel *model.Channel, patch *model.ChannelPatch, userId string) (*model.Channel, *model.AppError) { 502 oldChannelDisplayName := channel.DisplayName 503 oldChannelHeader := channel.Header 504 oldChannelPurpose := channel.Purpose 505 506 channel.Patch(patch) 507 channel, err := a.UpdateChannel(channel) 508 if err != nil { 509 return nil, err 510 } 511 512 if oldChannelDisplayName != channel.DisplayName { 513 if err := a.PostUpdateChannelDisplayNameMessage(userId, channel, oldChannelDisplayName, channel.DisplayName); err != nil { 514 mlog.Error(err.Error()) 515 } 516 } 517 518 if channel.Header != oldChannelHeader { 519 if err := a.PostUpdateChannelHeaderMessage(userId, channel, oldChannelHeader, channel.Header); err != nil { 520 mlog.Error(err.Error()) 521 } 522 } 523 524 if channel.Purpose != oldChannelPurpose { 525 if err := a.PostUpdateChannelPurposeMessage(userId, channel, oldChannelPurpose, channel.Purpose); err != nil { 526 mlog.Error(err.Error()) 527 } 528 } 529 530 return channel, err 531 } 532 533 func (a *App) GetSchemeRolesForChannel(channelId string) (string, string, *model.AppError) { 534 var channel *model.Channel 535 var err *model.AppError 536 537 if channel, err = a.GetChannel(channelId); err != nil { 538 return "", "", err 539 } 540 541 if channel.SchemeId != nil && len(*channel.SchemeId) != 0 { 542 scheme, err := a.GetScheme(*channel.SchemeId) 543 if err != nil { 544 return "", "", err 545 } 546 return scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil 547 } 548 549 var team *model.Team 550 551 if team, err = a.GetTeam(channel.TeamId); err != nil { 552 return "", "", err 553 } 554 555 if team.SchemeId != nil && len(*team.SchemeId) != 0 { 556 scheme, err := a.GetScheme(*team.SchemeId) 557 if err != nil { 558 return "", "", err 559 } 560 return scheme.DefaultChannelUserRole, scheme.DefaultChannelAdminRole, nil 561 } 562 563 return model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID, nil 564 } 565 566 func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError) { 567 var member *model.ChannelMember 568 var err *model.AppError 569 if member, err = a.GetChannelMember(channelId, userId); err != nil { 570 return nil, err 571 } 572 573 schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForChannel(channelId) 574 if err != nil { 575 return nil, err 576 } 577 578 var newExplicitRoles []string 579 member.SchemeUser = false 580 member.SchemeAdmin = false 581 582 for _, roleName := range strings.Fields(newRoles) { 583 role, err := a.GetRoleByName(roleName) 584 if err != nil { 585 err.StatusCode = http.StatusBadRequest 586 return nil, err 587 } 588 589 if !role.SchemeManaged { 590 // The role is not scheme-managed, so it's OK to apply it to the explicit roles field. 591 newExplicitRoles = append(newExplicitRoles, roleName) 592 } else { 593 // The role is scheme-managed, so need to check if it is part of the scheme for this channel or not. 594 switch roleName { 595 case schemeAdminRole: 596 member.SchemeAdmin = true 597 case schemeUserRole: 598 member.SchemeUser = true 599 default: 600 // If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role. 601 return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest) 602 } 603 } 604 } 605 606 member.ExplicitRoles = strings.Join(newExplicitRoles, " ") 607 608 result := <-a.Srv.Store.Channel().UpdateMember(member) 609 if result.Err != nil { 610 return nil, result.Err 611 } 612 member = result.Data.(*model.ChannelMember) 613 614 a.InvalidateCacheForUser(userId) 615 return member, nil 616 } 617 618 func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userId string, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError) { 619 member, err := a.GetChannelMember(channelId, userId) 620 if err != nil { 621 return nil, err 622 } 623 624 member.SchemeAdmin = isSchemeAdmin 625 member.SchemeUser = isSchemeUser 626 627 // If the migration is not completed, we also need to check the default channel_admin/channel_user roles are not present in the roles field. 628 if err = a.IsPhase2MigrationCompleted(); err != nil { 629 member.ExplicitRoles = RemoveRoles([]string{model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID}, member.ExplicitRoles) 630 } 631 632 result := <-a.Srv.Store.Channel().UpdateMember(member) 633 if result.Err != nil { 634 return nil, result.Err 635 } 636 member = result.Data.(*model.ChannelMember) 637 638 a.InvalidateCacheForUser(userId) 639 return member, nil 640 } 641 642 func (a *App) UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userId string) (*model.ChannelMember, *model.AppError) { 643 var member *model.ChannelMember 644 var err *model.AppError 645 if member, err = a.GetChannelMember(channelId, userId); err != nil { 646 return nil, err 647 } 648 649 // update whichever notify properties have been provided, but don't change the others 650 if markUnread, exists := data[model.MARK_UNREAD_NOTIFY_PROP]; exists { 651 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = markUnread 652 } 653 654 if desktop, exists := data[model.DESKTOP_NOTIFY_PROP]; exists { 655 member.NotifyProps[model.DESKTOP_NOTIFY_PROP] = desktop 656 } 657 658 if email, exists := data[model.EMAIL_NOTIFY_PROP]; exists { 659 member.NotifyProps[model.EMAIL_NOTIFY_PROP] = email 660 } 661 662 if push, exists := data[model.PUSH_NOTIFY_PROP]; exists { 663 member.NotifyProps[model.PUSH_NOTIFY_PROP] = push 664 } 665 666 result := <-a.Srv.Store.Channel().UpdateMember(member) 667 if result.Err != nil { 668 return nil, result.Err 669 } 670 671 a.InvalidateCacheForUser(userId) 672 a.InvalidateCacheForChannelMembersNotifyProps(channelId) 673 // Notify the clients that the member notify props changed 674 evt := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", userId, nil) 675 evt.Add("channelMember", member.ToJson()) 676 a.Publish(evt) 677 return member, nil 678 } 679 680 func (a *App) DeleteChannel(channel *model.Channel, userId string) *model.AppError { 681 ihc := a.Srv.Store.Webhook().GetIncomingByChannel(channel.Id) 682 ohc := a.Srv.Store.Webhook().GetOutgoingByChannel(channel.Id, -1, -1) 683 684 var user *model.User 685 if userId != "" { 686 uc := a.Srv.Store.User().Get(userId) 687 uresult := <-uc 688 if uresult.Err != nil { 689 return uresult.Err 690 } 691 user = uresult.Data.(*model.User) 692 } 693 694 ihcresult := <-ihc 695 if ihcresult.Err != nil { 696 return ihcresult.Err 697 } 698 699 ohcresult := <-ohc 700 if ohcresult.Err != nil { 701 return ohcresult.Err 702 } 703 704 incomingHooks := ihcresult.Data.([]*model.IncomingWebhook) 705 outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook) 706 707 if channel.DeleteAt > 0 { 708 err := model.NewAppError("deleteChannel", "api.channel.delete_channel.deleted.app_error", nil, "", http.StatusBadRequest) 709 return err 710 } 711 712 if channel.Name == model.DEFAULT_CHANNEL { 713 err := model.NewAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest) 714 return err 715 } 716 717 if user != nil { 718 T := utils.GetUserTranslations(user.Locale) 719 720 post := &model.Post{ 721 ChannelId: channel.Id, 722 Message: fmt.Sprintf(T("api.channel.delete_channel.archived"), user.Username), 723 Type: model.POST_CHANNEL_DELETED, 724 UserId: userId, 725 Props: model.StringInterface{ 726 "username": user.Username, 727 }, 728 } 729 730 if _, err := a.CreatePost(post, channel, false); err != nil { 731 mlog.Error(fmt.Sprintf("Failed to post archive message %v", err)) 732 } 733 } 734 735 now := model.GetMillis() 736 for _, hook := range incomingHooks { 737 if result := <-a.Srv.Store.Webhook().DeleteIncoming(hook.Id, now); result.Err != nil { 738 mlog.Error(fmt.Sprintf("Encountered error deleting incoming webhook, id=%v", hook.Id)) 739 } 740 a.InvalidateCacheForWebhook(hook.Id) 741 } 742 743 for _, hook := range outgoingHooks { 744 if result := <-a.Srv.Store.Webhook().DeleteOutgoing(hook.Id, now); result.Err != nil { 745 mlog.Error(fmt.Sprintf("Encountered error deleting outgoing webhook, id=%v", hook.Id)) 746 } 747 } 748 749 deleteAt := model.GetMillis() 750 751 if dresult := <-a.Srv.Store.Channel().Delete(channel.Id, deleteAt); dresult.Err != nil { 752 return dresult.Err 753 } 754 a.InvalidateCacheForChannel(channel) 755 756 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil) 757 message.Add("channel_id", channel.Id) 758 message.Add("delete_at", deleteAt) 759 a.Publish(message) 760 761 return nil 762 } 763 764 func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMember *model.TeamMember) (*model.ChannelMember, *model.AppError) { 765 if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE { 766 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest) 767 } 768 769 cmchan := a.Srv.Store.Channel().GetMember(channel.Id, user.Id) 770 771 if result := <-cmchan; result.Err != nil { 772 if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 773 return nil, result.Err 774 } 775 } else { 776 channelMember := result.Data.(*model.ChannelMember) 777 return channelMember, nil 778 } 779 780 newMember := &model.ChannelMember{ 781 ChannelId: channel.Id, 782 UserId: user.Id, 783 NotifyProps: model.GetDefaultChannelNotifyProps(), 784 SchemeUser: true, 785 } 786 if result := <-a.Srv.Store.Channel().SaveMember(newMember); result.Err != nil { 787 mlog.Error(fmt.Sprintf("Failed to add member user_id=%v channel_id=%v err=%v", user.Id, channel.Id, result.Err), mlog.String("user_id", user.Id)) 788 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "", http.StatusInternalServerError) 789 } 790 a.WaitForChannelMembership(channel.Id, user.Id) 791 792 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); result.Err != nil { 793 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 794 } 795 796 a.InvalidateCacheForUser(user.Id) 797 a.InvalidateCacheForChannelMembers(channel.Id) 798 799 return newMember, nil 800 } 801 802 func (a *App) AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) { 803 tmchan := a.Srv.Store.Team().GetMember(channel.TeamId, user.Id) 804 var teamMember *model.TeamMember 805 806 result := <-tmchan 807 if result.Err != nil { 808 return nil, result.Err 809 } 810 teamMember = result.Data.(*model.TeamMember) 811 if teamMember.DeleteAt > 0 { 812 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "", http.StatusBadRequest) 813 } 814 815 newMember, err := a.addUserToChannel(user, channel, teamMember) 816 if err != nil { 817 return nil, err 818 } 819 820 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil) 821 message.Add("user_id", user.Id) 822 message.Add("team_id", channel.TeamId) 823 a.Publish(message) 824 825 return newMember, nil 826 } 827 828 func (a *App) AddChannelMember(userId string, channel *model.Channel, userRequestorId string, postRootId string, clearPushNotifications bool) (*model.ChannelMember, *model.AppError) { 829 if result := <-a.Srv.Store.Channel().GetMember(channel.Id, userId); result.Err != nil { 830 if result.Err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 831 return nil, result.Err 832 } 833 } else { 834 return result.Data.(*model.ChannelMember), nil 835 } 836 837 var user *model.User 838 var err *model.AppError 839 840 if user, err = a.GetUser(userId); err != nil { 841 return nil, err 842 } 843 844 var userRequestor *model.User 845 if userRequestorId != "" { 846 if userRequestor, err = a.GetUser(userRequestorId); err != nil { 847 return nil, err 848 } 849 } 850 851 cm, err := a.AddUserToChannel(user, channel) 852 if err != nil { 853 return nil, err 854 } 855 856 if a.PluginsReady() { 857 a.Go(func() { 858 pluginContext := &plugin.Context{} 859 a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 860 hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor) 861 return true 862 }, plugin.UserHasJoinedChannelId) 863 }) 864 } 865 866 if userRequestorId == "" || userId == userRequestorId { 867 a.postJoinChannelMessage(user, channel) 868 } else { 869 a.Go(func() { 870 a.PostAddToChannelMessage(userRequestor, user, channel, postRootId) 871 }) 872 } 873 874 if userRequestor != nil { 875 a.MarkChannelsAsViewed([]string{channel.Id}, userRequestor.Id, clearPushNotifications) 876 } 877 878 return cm, nil 879 } 880 881 func (a *App) AddDirectChannels(teamId string, user *model.User) *model.AppError { 882 var profiles []*model.User 883 result := <-a.Srv.Store.User().GetProfiles(teamId, 0, 100) 884 if result.Err != nil { 885 return model.NewAppError("AddDirectChannels", "api.user.add_direct_channels_and_forget.failed.error", map[string]interface{}{"UserId": user.Id, "TeamId": teamId, "Error": result.Err.Error()}, "", http.StatusInternalServerError) 886 } 887 profiles = result.Data.([]*model.User) 888 889 var preferences model.Preferences 890 891 for _, profile := range profiles { 892 if profile.Id == user.Id { 893 continue 894 } 895 896 preference := model.Preference{ 897 UserId: user.Id, 898 Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, 899 Name: profile.Id, 900 Value: "true", 901 } 902 903 preferences = append(preferences, preference) 904 905 if len(preferences) >= 10 { 906 break 907 } 908 } 909 910 if result := <-a.Srv.Store.Preference().Save(&preferences); result.Err != nil { 911 return model.NewAppError("AddDirectChannels", "api.user.add_direct_channels_and_forget.failed.error", map[string]interface{}{"UserId": user.Id, "TeamId": teamId, "Error": result.Err.Error()}, "", http.StatusInternalServerError) 912 } 913 914 return nil 915 } 916 917 func (a *App) PostUpdateChannelHeaderMessage(userId string, channel *model.Channel, oldChannelHeader, newChannelHeader string) *model.AppError { 918 uc := a.Srv.Store.User().Get(userId) 919 920 uresult := <-uc 921 if uresult.Err != nil { 922 return model.NewAppError("PostUpdateChannelHeaderMessage", "api.channel.post_update_channel_header_message_and_forget.retrieve_user.error", nil, uresult.Err.Error(), http.StatusBadRequest) 923 } 924 925 user := uresult.Data.(*model.User) 926 927 var message string 928 if oldChannelHeader == "" { 929 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_to"), user.Username, newChannelHeader) 930 } else if newChannelHeader == "" { 931 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.removed"), user.Username, oldChannelHeader) 932 } else { 933 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_from"), user.Username, oldChannelHeader, newChannelHeader) 934 } 935 936 post := &model.Post{ 937 ChannelId: channel.Id, 938 Message: message, 939 Type: model.POST_HEADER_CHANGE, 940 UserId: userId, 941 Props: model.StringInterface{ 942 "username": user.Username, 943 "old_header": oldChannelHeader, 944 "new_header": newChannelHeader, 945 }, 946 } 947 948 if _, err := a.CreatePost(post, channel, false); err != nil { 949 return model.NewAppError("", "api.channel.post_update_channel_header_message_and_forget.post.error", nil, err.Error(), http.StatusInternalServerError) 950 } 951 952 return nil 953 } 954 955 func (a *App) PostUpdateChannelPurposeMessage(userId string, channel *model.Channel, oldChannelPurpose string, newChannelPurpose string) *model.AppError { 956 uc := a.Srv.Store.User().Get(userId) 957 958 uresult := <-uc 959 if uresult.Err != nil { 960 return model.NewAppError("PostUpdateChannelPurposeMessage", "app.channel.post_update_channel_purpose_message.retrieve_user.error", nil, uresult.Err.Error(), http.StatusBadRequest) 961 } 962 963 user := uresult.Data.(*model.User) 964 965 var message string 966 if oldChannelPurpose == "" { 967 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_to"), user.Username, newChannelPurpose) 968 } else if newChannelPurpose == "" { 969 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.removed"), user.Username, oldChannelPurpose) 970 } else { 971 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_from"), user.Username, oldChannelPurpose, newChannelPurpose) 972 } 973 974 post := &model.Post{ 975 ChannelId: channel.Id, 976 Message: message, 977 Type: model.POST_PURPOSE_CHANGE, 978 UserId: userId, 979 Props: model.StringInterface{ 980 "username": user.Username, 981 "old_purpose": oldChannelPurpose, 982 "new_purpose": newChannelPurpose, 983 }, 984 } 985 if _, err := a.CreatePost(post, channel, false); err != nil { 986 return model.NewAppError("", "app.channel.post_update_channel_purpose_message.post.error", nil, err.Error(), http.StatusInternalServerError) 987 } 988 989 return nil 990 } 991 992 func (a *App) PostUpdateChannelDisplayNameMessage(userId string, channel *model.Channel, oldChannelDisplayName, newChannelDisplayName string) *model.AppError { 993 uc := a.Srv.Store.User().Get(userId) 994 995 uresult := <-uc 996 if uresult.Err != nil { 997 return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.retrieve_user.error", nil, uresult.Err.Error(), http.StatusBadRequest) 998 } 999 1000 user := uresult.Data.(*model.User) 1001 1002 message := fmt.Sprintf(utils.T("api.channel.post_update_channel_displayname_message_and_forget.updated_from"), user.Username, oldChannelDisplayName, newChannelDisplayName) 1003 1004 post := &model.Post{ 1005 ChannelId: channel.Id, 1006 Message: message, 1007 Type: model.POST_DISPLAYNAME_CHANGE, 1008 UserId: userId, 1009 Props: model.StringInterface{ 1010 "username": user.Username, 1011 "old_displayname": oldChannelDisplayName, 1012 "new_displayname": newChannelDisplayName, 1013 }, 1014 } 1015 1016 if _, err := a.CreatePost(post, channel, false); err != nil { 1017 return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.create_post.error", nil, err.Error(), http.StatusInternalServerError) 1018 } 1019 1020 return nil 1021 } 1022 1023 func (a *App) GetChannel(channelId string) (*model.Channel, *model.AppError) { 1024 result := <-a.Srv.Store.Channel().Get(channelId, true) 1025 if result.Err != nil { 1026 if result.Err.Id == "store.sql_channel.get.existing.app_error" { 1027 result.Err.StatusCode = http.StatusNotFound 1028 return nil, result.Err 1029 } 1030 result.Err.StatusCode = http.StatusBadRequest 1031 return nil, result.Err 1032 } 1033 return result.Data.(*model.Channel), nil 1034 } 1035 1036 func (a *App) GetChannelByName(channelName, teamId string, includeDeleted bool) (*model.Channel, *model.AppError) { 1037 var result store.StoreResult 1038 1039 if includeDeleted { 1040 result = <-a.Srv.Store.Channel().GetByNameIncludeDeleted(teamId, channelName, false) 1041 } else { 1042 result = <-a.Srv.Store.Channel().GetByName(teamId, channelName, false) 1043 } 1044 1045 if result.Err != nil && result.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { 1046 result.Err.StatusCode = http.StatusNotFound 1047 return nil, result.Err 1048 } 1049 1050 if result.Err != nil { 1051 result.Err.StatusCode = http.StatusBadRequest 1052 return nil, result.Err 1053 } 1054 1055 return result.Data.(*model.Channel), nil 1056 } 1057 1058 func (a *App) GetChannelsByNames(channelNames []string, teamId string) ([]*model.Channel, *model.AppError) { 1059 result := <-a.Srv.Store.Channel().GetByNames(teamId, channelNames, true) 1060 if result.Err != nil { 1061 if result.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { 1062 result.Err.StatusCode = http.StatusNotFound 1063 return nil, result.Err 1064 } 1065 result.Err.StatusCode = http.StatusBadRequest 1066 return nil, result.Err 1067 } 1068 return result.Data.([]*model.Channel), nil 1069 } 1070 1071 func (a *App) GetChannelByNameForTeamName(channelName, teamName string, includeDeleted bool) (*model.Channel, *model.AppError) { 1072 var team *model.Team 1073 1074 result := <-a.Srv.Store.Team().GetByName(teamName) 1075 if result.Err != nil { 1076 result.Err.StatusCode = http.StatusNotFound 1077 return nil, result.Err 1078 } 1079 team = result.Data.(*model.Team) 1080 1081 if includeDeleted { 1082 result = <-a.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, channelName, false) 1083 } else { 1084 result = <-a.Srv.Store.Channel().GetByName(team.Id, channelName, false) 1085 } 1086 1087 if result.Err != nil && result.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { 1088 result.Err.StatusCode = http.StatusNotFound 1089 return nil, result.Err 1090 } 1091 1092 if result.Err != nil { 1093 result.Err.StatusCode = http.StatusBadRequest 1094 return nil, result.Err 1095 } 1096 1097 return result.Data.(*model.Channel), nil 1098 } 1099 1100 func (a *App) GetChannelsForUser(teamId string, userId string, includeDeleted bool) (*model.ChannelList, *model.AppError) { 1101 result := <-a.Srv.Store.Channel().GetChannels(teamId, userId, includeDeleted) 1102 if result.Err != nil { 1103 return nil, result.Err 1104 } 1105 return result.Data.(*model.ChannelList), nil 1106 } 1107 1108 func (a *App) GetDeletedChannels(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1109 result := <-a.Srv.Store.Channel().GetDeleted(teamId, offset, limit) 1110 if result.Err != nil { 1111 return nil, result.Err 1112 } 1113 return result.Data.(*model.ChannelList), nil 1114 } 1115 1116 func (a *App) GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1117 result := <-a.Srv.Store.Channel().GetMoreChannels(teamId, userId, offset, limit) 1118 if result.Err != nil { 1119 return nil, result.Err 1120 } 1121 return result.Data.(*model.ChannelList), nil 1122 } 1123 1124 func (a *App) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) (*model.ChannelList, *model.AppError) { 1125 result := <-a.Srv.Store.Channel().GetPublicChannelsByIdsForTeam(teamId, channelIds) 1126 if result.Err != nil { 1127 return nil, result.Err 1128 } 1129 return result.Data.(*model.ChannelList), nil 1130 } 1131 1132 func (a *App) GetPublicChannelsForTeam(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1133 result := <-a.Srv.Store.Channel().GetPublicChannelsForTeam(teamId, offset, limit) 1134 if result.Err != nil { 1135 return nil, result.Err 1136 } 1137 return result.Data.(*model.ChannelList), nil 1138 } 1139 1140 func (a *App) GetChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError) { 1141 result := <-a.Srv.Store.Channel().GetMember(channelId, userId) 1142 if result.Err != nil { 1143 return nil, result.Err 1144 } 1145 return result.Data.(*model.ChannelMember), nil 1146 } 1147 1148 func (a *App) GetChannelMembersPage(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError) { 1149 result := <-a.Srv.Store.Channel().GetMembers(channelId, page*perPage, perPage) 1150 if result.Err != nil { 1151 return nil, result.Err 1152 } 1153 return result.Data.(*model.ChannelMembers), nil 1154 } 1155 1156 func (a *App) GetChannelMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError) { 1157 result := <-a.Srv.Store.Channel().GetMembersByIds(channelId, userIds) 1158 if result.Err != nil { 1159 return nil, result.Err 1160 } 1161 return result.Data.(*model.ChannelMembers), nil 1162 } 1163 1164 func (a *App) GetChannelMembersForUser(teamId string, userId string) (*model.ChannelMembers, *model.AppError) { 1165 result := <-a.Srv.Store.Channel().GetMembersForUser(teamId, userId) 1166 if result.Err != nil { 1167 return nil, result.Err 1168 } 1169 return result.Data.(*model.ChannelMembers), nil 1170 } 1171 1172 func (a *App) GetChannelMemberCount(channelId string) (int64, *model.AppError) { 1173 result := <-a.Srv.Store.Channel().GetMemberCount(channelId, true) 1174 if result.Err != nil { 1175 return 0, result.Err 1176 } 1177 return result.Data.(int64), nil 1178 } 1179 1180 func (a *App) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, *model.AppError) { 1181 result := <-a.Srv.Store.Channel().GetChannelCounts(teamId, userId) 1182 if result.Err != nil { 1183 return nil, result.Err 1184 } 1185 return result.Data.(*model.ChannelCounts), nil 1186 } 1187 1188 func (a *App) GetChannelUnread(channelId, userId string) (*model.ChannelUnread, *model.AppError) { 1189 result := <-a.Srv.Store.Channel().GetChannelUnread(channelId, userId) 1190 if result.Err != nil { 1191 return nil, result.Err 1192 } 1193 channelUnread := result.Data.(*model.ChannelUnread) 1194 1195 if channelUnread.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_MARK_UNREAD_MENTION { 1196 channelUnread.MsgCount = 0 1197 } 1198 1199 return channelUnread, nil 1200 } 1201 1202 func (a *App) JoinChannel(channel *model.Channel, userId string) *model.AppError { 1203 userChan := a.Srv.Store.User().Get(userId) 1204 memberChan := a.Srv.Store.Channel().GetMember(channel.Id, userId) 1205 1206 uresult := <-userChan 1207 if uresult.Err != nil { 1208 return uresult.Err 1209 } 1210 1211 mresult := <-memberChan 1212 if mresult.Err == nil && mresult.Data != nil { 1213 // user is already in the channel 1214 return nil 1215 } 1216 1217 user := uresult.Data.(*model.User) 1218 1219 if channel.Type != model.CHANNEL_OPEN { 1220 return model.NewAppError("JoinChannel", "api.channel.join_channel.permissions.app_error", nil, "", http.StatusBadRequest) 1221 } 1222 1223 cm, err := a.AddUserToChannel(user, channel) 1224 if err != nil { 1225 return err 1226 } 1227 1228 if a.PluginsReady() { 1229 a.Go(func() { 1230 pluginContext := &plugin.Context{} 1231 a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 1232 hooks.UserHasJoinedChannel(pluginContext, cm, nil) 1233 return true 1234 }, plugin.UserHasJoinedChannelId) 1235 }) 1236 } 1237 1238 if err := a.postJoinChannelMessage(user, channel); err != nil { 1239 return err 1240 } 1241 1242 return nil 1243 } 1244 1245 func (a *App) postJoinChannelMessage(user *model.User, channel *model.Channel) *model.AppError { 1246 post := &model.Post{ 1247 ChannelId: channel.Id, 1248 Message: fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username), 1249 Type: model.POST_JOIN_CHANNEL, 1250 UserId: user.Id, 1251 Props: model.StringInterface{ 1252 "username": user.Username, 1253 }, 1254 } 1255 1256 if _, err := a.CreatePost(post, channel, false); err != nil { 1257 return model.NewAppError("postJoinChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1258 } 1259 1260 return nil 1261 } 1262 1263 func (a *App) postJoinTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 1264 post := &model.Post{ 1265 ChannelId: channel.Id, 1266 Message: fmt.Sprintf(utils.T("api.team.join_team.post_and_forget"), user.Username), 1267 Type: model.POST_JOIN_TEAM, 1268 UserId: user.Id, 1269 Props: model.StringInterface{ 1270 "username": user.Username, 1271 }, 1272 } 1273 1274 if _, err := a.CreatePost(post, channel, false); err != nil { 1275 return model.NewAppError("postJoinTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1276 } 1277 1278 return nil 1279 } 1280 1281 func (a *App) LeaveChannel(channelId string, userId string) *model.AppError { 1282 sc := a.Srv.Store.Channel().Get(channelId, true) 1283 uc := a.Srv.Store.User().Get(userId) 1284 ccm := a.Srv.Store.Channel().GetMemberCount(channelId, false) 1285 1286 cresult := <-sc 1287 if cresult.Err != nil { 1288 return cresult.Err 1289 } 1290 uresult := <-uc 1291 if uresult.Err != nil { 1292 return cresult.Err 1293 } 1294 ccmresult := <-ccm 1295 if ccmresult.Err != nil { 1296 return ccmresult.Err 1297 } 1298 1299 channel := cresult.Data.(*model.Channel) 1300 user := uresult.Data.(*model.User) 1301 membersCount := ccmresult.Data.(int64) 1302 1303 if channel.IsGroupOrDirect() { 1304 err := model.NewAppError("LeaveChannel", "api.channel.leave.direct.app_error", nil, "", http.StatusBadRequest) 1305 return err 1306 } 1307 1308 if channel.Type == model.CHANNEL_PRIVATE && membersCount == 1 { 1309 err := model.NewAppError("LeaveChannel", "api.channel.leave.last_member.app_error", nil, "userId="+user.Id, http.StatusBadRequest) 1310 return err 1311 } 1312 1313 if err := a.removeUserFromChannel(userId, userId, channel); err != nil { 1314 return err 1315 } 1316 1317 if channel.Name == model.DEFAULT_CHANNEL && !*a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 1318 return nil 1319 } 1320 1321 a.Go(func() { 1322 a.postLeaveChannelMessage(user, channel) 1323 }) 1324 1325 return nil 1326 } 1327 1328 func (a *App) postLeaveChannelMessage(user *model.User, channel *model.Channel) *model.AppError { 1329 post := &model.Post{ 1330 ChannelId: channel.Id, 1331 Message: fmt.Sprintf(utils.T("api.channel.leave.left"), user.Username), 1332 Type: model.POST_LEAVE_CHANNEL, 1333 UserId: user.Id, 1334 Props: model.StringInterface{ 1335 "username": user.Username, 1336 }, 1337 } 1338 1339 if _, err := a.CreatePost(post, channel, false); err != nil { 1340 return model.NewAppError("postLeaveChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1341 } 1342 1343 return nil 1344 } 1345 1346 func (a *App) PostAddToChannelMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError { 1347 post := &model.Post{ 1348 ChannelId: channel.Id, 1349 Message: fmt.Sprintf(utils.T("api.channel.add_member.added"), addedUser.Username, user.Username), 1350 Type: model.POST_ADD_TO_CHANNEL, 1351 UserId: user.Id, 1352 RootId: postRootId, 1353 Props: model.StringInterface{ 1354 "userId": user.Id, 1355 "username": user.Username, 1356 model.POST_PROPS_ADDED_USER_ID: addedUser.Id, 1357 "addedUsername": addedUser.Username, 1358 }, 1359 } 1360 1361 if _, err := a.CreatePost(post, channel, false); err != nil { 1362 return model.NewAppError("postAddToChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1363 } 1364 1365 return nil 1366 } 1367 1368 func (a *App) postAddToTeamMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError { 1369 post := &model.Post{ 1370 ChannelId: channel.Id, 1371 Message: fmt.Sprintf(utils.T("api.team.add_user_to_team.added"), addedUser.Username, user.Username), 1372 Type: model.POST_ADD_TO_TEAM, 1373 UserId: user.Id, 1374 RootId: postRootId, 1375 Props: model.StringInterface{ 1376 "userId": user.Id, 1377 "username": user.Username, 1378 model.POST_PROPS_ADDED_USER_ID: addedUser.Id, 1379 "addedUsername": addedUser.Username, 1380 }, 1381 } 1382 1383 if _, err := a.CreatePost(post, channel, false); err != nil { 1384 return model.NewAppError("postAddToTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1385 } 1386 1387 return nil 1388 } 1389 1390 func (a *App) postRemoveFromChannelMessage(removerUserId string, removedUser *model.User, channel *model.Channel) *model.AppError { 1391 post := &model.Post{ 1392 ChannelId: channel.Id, 1393 Message: fmt.Sprintf(utils.T("api.channel.remove_member.removed"), removedUser.Username), 1394 Type: model.POST_REMOVE_FROM_CHANNEL, 1395 UserId: removerUserId, 1396 Props: model.StringInterface{ 1397 "removedUserId": removedUser.Id, 1398 "removedUsername": removedUser.Username, 1399 }, 1400 } 1401 1402 if _, err := a.CreatePost(post, channel, false); err != nil { 1403 return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1404 } 1405 1406 return nil 1407 } 1408 1409 func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { 1410 if channel.Name == model.DEFAULT_CHANNEL { 1411 return model.NewAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest) 1412 } 1413 1414 cm, err := a.GetChannelMember(channel.Id, userIdToRemove) 1415 if err != nil { 1416 return err 1417 } 1418 1419 if cmresult := <-a.Srv.Store.Channel().RemoveMember(channel.Id, userIdToRemove); cmresult.Err != nil { 1420 return cmresult.Err 1421 } 1422 if cmhResult := <-a.Srv.Store.ChannelMemberHistory().LogLeaveEvent(userIdToRemove, channel.Id, model.GetMillis()); cmhResult.Err != nil { 1423 return cmhResult.Err 1424 } 1425 1426 a.InvalidateCacheForUser(userIdToRemove) 1427 a.InvalidateCacheForChannelMembers(channel.Id) 1428 1429 if a.PluginsReady() { 1430 1431 var actorUser *model.User 1432 if removerUserId != "" { 1433 actorUser, _ = a.GetUser(removerUserId) 1434 } 1435 1436 a.Go(func() { 1437 pluginContext := &plugin.Context{} 1438 a.Plugins.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 1439 hooks.UserHasLeftChannel(pluginContext, cm, actorUser) 1440 return true 1441 }, plugin.UserHasLeftChannelId) 1442 }) 1443 } 1444 1445 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil) 1446 message.Add("user_id", userIdToRemove) 1447 message.Add("remover_id", removerUserId) 1448 a.Publish(message) 1449 1450 // because the removed user no longer belongs to the channel we need to send a separate websocket event 1451 userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil) 1452 userMsg.Add("channel_id", channel.Id) 1453 userMsg.Add("remover_id", removerUserId) 1454 a.Publish(userMsg) 1455 1456 return nil 1457 } 1458 1459 func (a *App) RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { 1460 var err *model.AppError 1461 1462 if err = a.removeUserFromChannel(userIdToRemove, removerUserId, channel); err != nil { 1463 return err 1464 } 1465 1466 var user *model.User 1467 if user, err = a.GetUser(userIdToRemove); err != nil { 1468 return err 1469 } 1470 1471 if userIdToRemove == removerUserId { 1472 a.postLeaveChannelMessage(user, channel) 1473 } else { 1474 a.Go(func() { 1475 a.postRemoveFromChannelMessage(removerUserId, user, channel) 1476 }) 1477 } 1478 1479 return nil 1480 } 1481 1482 func (a *App) GetNumberOfChannelsOnTeam(teamId string) (int, *model.AppError) { 1483 // Get total number of channels on current team 1484 result := <-a.Srv.Store.Channel().GetTeamChannels(teamId) 1485 if result.Err != nil { 1486 return 0, result.Err 1487 } 1488 return len(*result.Data.(*model.ChannelList)), nil 1489 } 1490 1491 func (a *App) SetActiveChannel(userId string, channelId string) *model.AppError { 1492 status, err := a.GetStatus(userId) 1493 1494 oldStatus := model.STATUS_OFFLINE 1495 1496 if err != nil { 1497 status = &model.Status{UserId: userId, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: channelId} 1498 } else { 1499 oldStatus = status.Status 1500 status.ActiveChannel = channelId 1501 if !status.Manual && channelId != "" { 1502 status.Status = model.STATUS_ONLINE 1503 } 1504 status.LastActivityAt = model.GetMillis() 1505 } 1506 1507 a.AddStatusCache(status) 1508 1509 if status.Status != oldStatus { 1510 a.BroadcastStatus(status) 1511 } 1512 1513 return nil 1514 } 1515 1516 func (a *App) UpdateChannelLastViewedAt(channelIds []string, userId string) *model.AppError { 1517 if result := <-a.Srv.Store.Channel().UpdateLastViewedAt(channelIds, userId); result.Err != nil { 1518 return result.Err 1519 } 1520 1521 if *a.Config().ServiceSettings.EnableChannelViewedMessages { 1522 for _, channelId := range channelIds { 1523 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) 1524 message.Add("channel_id", channelId) 1525 a.Publish(message) 1526 } 1527 } 1528 1529 return nil 1530 } 1531 1532 func (a *App) AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError) { 1533 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 1534 1535 result := <-a.Srv.Store.Channel().AutocompleteInTeam(teamId, term, includeDeleted) 1536 if result.Err != nil { 1537 return nil, result.Err 1538 } 1539 return result.Data.(*model.ChannelList), nil 1540 } 1541 1542 func (a *App) AutocompleteChannelsForSearch(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { 1543 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 1544 1545 result := <-a.Srv.Store.Channel().AutocompleteInTeamForSearch(teamId, userId, term, includeDeleted) 1546 if result.Err != nil { 1547 return nil, result.Err 1548 } 1549 return result.Data.(*model.ChannelList), nil 1550 } 1551 1552 func (a *App) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) { 1553 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 1554 1555 result := <-a.Srv.Store.Channel().SearchInTeam(teamId, term, includeDeleted) 1556 if result.Err != nil { 1557 return nil, result.Err 1558 } 1559 return result.Data.(*model.ChannelList), nil 1560 } 1561 1562 func (a *App) SearchChannelsUserNotIn(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { 1563 result := <-a.Srv.Store.Channel().SearchMore(userId, teamId, term) 1564 if result.Err != nil { 1565 return nil, result.Err 1566 } 1567 return result.Data.(*model.ChannelList), nil 1568 } 1569 1570 func (a *App) MarkChannelsAsViewed(channelIds []string, userId string, clearPushNotifications bool) (map[string]int64, *model.AppError) { 1571 // I start looking for channels with notifications before I mark it as read, to clear the push notifications if needed 1572 channelsToClearPushNotifications := []string{} 1573 if *a.Config().EmailSettings.SendPushNotifications && clearPushNotifications { 1574 for _, channelId := range channelIds { 1575 if model.IsValidId(channelId) { 1576 result := <-a.Srv.Store.Channel().GetMember(channelId, userId) 1577 if result.Err != nil { 1578 mlog.Warn(fmt.Sprintf("Failed to get membership %v", result.Err)) 1579 continue 1580 } 1581 member := result.Data.(*model.ChannelMember) 1582 1583 notify := member.NotifyProps[model.PUSH_NOTIFY_PROP] 1584 if notify == model.CHANNEL_NOTIFY_DEFAULT { 1585 user, _ := a.GetUser(userId) 1586 notify = user.NotifyProps[model.PUSH_NOTIFY_PROP] 1587 } 1588 if notify == model.USER_NOTIFY_ALL { 1589 if result := <-a.Srv.Store.User().GetAnyUnreadPostCountForChannel(userId, channelId); result.Err == nil { 1590 if result.Data.(int64) > 0 { 1591 channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId) 1592 } 1593 } 1594 } else if notify == model.USER_NOTIFY_MENTION { 1595 if result := <-a.Srv.Store.User().GetUnreadCountForChannel(userId, channelId); result.Err == nil { 1596 if result.Data.(int64) > 0 { 1597 channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId) 1598 } 1599 } 1600 } 1601 } 1602 } 1603 } 1604 result := <-a.Srv.Store.Channel().UpdateLastViewedAt(channelIds, userId) 1605 if result.Err != nil { 1606 return nil, result.Err 1607 } 1608 1609 times := result.Data.(map[string]int64) 1610 if *a.Config().ServiceSettings.EnableChannelViewedMessages { 1611 for _, channelId := range channelIds { 1612 if model.IsValidId(channelId) { 1613 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) 1614 message.Add("channel_id", channelId) 1615 a.Publish(message) 1616 } 1617 } 1618 } 1619 for _, channelId := range channelsToClearPushNotifications { 1620 a.ClearPushNotification(userId, channelId) 1621 } 1622 return times, nil 1623 } 1624 1625 func (a *App) ViewChannel(view *model.ChannelView, userId string, clearPushNotifications bool) (map[string]int64, *model.AppError) { 1626 if err := a.SetActiveChannel(userId, view.ChannelId); err != nil { 1627 return nil, err 1628 } 1629 1630 channelIds := []string{} 1631 1632 if len(view.ChannelId) > 0 { 1633 channelIds = append(channelIds, view.ChannelId) 1634 } 1635 1636 if len(view.PrevChannelId) > 0 { 1637 channelIds = append(channelIds, view.PrevChannelId) 1638 } 1639 1640 if len(channelIds) == 0 { 1641 return map[string]int64{}, nil 1642 } 1643 1644 return a.MarkChannelsAsViewed(channelIds, userId, clearPushNotifications) 1645 } 1646 1647 func (a *App) PermanentDeleteChannel(channel *model.Channel) *model.AppError { 1648 if result := <-a.Srv.Store.Post().PermanentDeleteByChannel(channel.Id); result.Err != nil { 1649 return result.Err 1650 } 1651 1652 if result := <-a.Srv.Store.Channel().PermanentDeleteMembersByChannel(channel.Id); result.Err != nil { 1653 return result.Err 1654 } 1655 1656 if result := <-a.Srv.Store.Webhook().PermanentDeleteIncomingByChannel(channel.Id); result.Err != nil { 1657 return result.Err 1658 } 1659 1660 if result := <-a.Srv.Store.Webhook().PermanentDeleteOutgoingByChannel(channel.Id); result.Err != nil { 1661 return result.Err 1662 } 1663 1664 if result := <-a.Srv.Store.Channel().PermanentDelete(channel.Id); result.Err != nil { 1665 return result.Err 1666 } 1667 1668 return nil 1669 } 1670 1671 // This function is intended for use from the CLI. It is not robust against people joining the channel while the move 1672 // is in progress, and therefore should not be used from the API without first fixing this potential race condition. 1673 func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.User) *model.AppError { 1674 // Check that all channel members are in the destination team. 1675 channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000) 1676 if err != nil { 1677 return err 1678 } 1679 1680 channelMemberIds := []string{} 1681 for _, channelMember := range *channelMembers { 1682 channelMemberIds = append(channelMemberIds, channelMember.UserId) 1683 } 1684 1685 teamMembers, err2 := a.GetTeamMembersByIds(team.Id, channelMemberIds) 1686 if err2 != nil { 1687 return err2 1688 } 1689 1690 if len(teamMembers) != len(*channelMembers) { 1691 return model.NewAppError("MoveChannel", "app.channel.move_channel.members_do_not_match.error", nil, "", http.StatusInternalServerError) 1692 } 1693 1694 // keep instance of the previous team 1695 var previousTeam *model.Team 1696 result := <-a.Srv.Store.Team().Get(channel.TeamId) 1697 if result.Err != nil { 1698 return result.Err 1699 } 1700 previousTeam = result.Data.(*model.Team) 1701 1702 channel.TeamId = team.Id 1703 if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil { 1704 return result.Err 1705 } 1706 a.postChannelMoveMessage(user, channel, previousTeam) 1707 1708 return nil 1709 } 1710 1711 func (a *App) postChannelMoveMessage(user *model.User, channel *model.Channel, previousTeam *model.Team) *model.AppError { 1712 1713 post := &model.Post{ 1714 ChannelId: channel.Id, 1715 Message: fmt.Sprintf(utils.T("api.team.move_channel.success"), previousTeam.Name), 1716 Type: model.POST_MOVE_CHANNEL, 1717 UserId: user.Id, 1718 Props: model.StringInterface{ 1719 "username": user.Username, 1720 }, 1721 } 1722 1723 if _, err := a.CreatePost(post, channel, false); err != nil { 1724 return model.NewAppError("postChannelMoveMessage", "api.team.move_channel.post.error", nil, err.Error(), http.StatusInternalServerError) 1725 } 1726 1727 return nil 1728 } 1729 1730 func (a *App) GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) { 1731 result := <-a.Srv.Store.Channel().GetPinnedPosts(channelId) 1732 if result.Err != nil { 1733 return nil, result.Err 1734 } 1735 return result.Data.(*model.PostList), nil 1736 } 1737 1738 func (a *App) GetDirectChannel(userId1, userId2 string) (*model.Channel, *model.AppError) { 1739 result := <-a.Srv.Store.Channel().GetByName("", model.GetDMNameFromIds(userId1, userId2), true) 1740 if result.Err != nil { 1741 if result.Err.Id == store.MISSING_CHANNEL_ERROR { 1742 result := <-a.Srv.Store.Channel().CreateDirectChannel(userId1, userId2) 1743 if result.Err != nil { 1744 return nil, model.NewAppError("GetOrCreateDMChannel", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message, http.StatusBadRequest) 1745 } 1746 a.InvalidateCacheForUser(userId1) 1747 a.InvalidateCacheForUser(userId2) 1748 1749 channel := result.Data.(*model.Channel) 1750 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId1, channel.Id, model.GetMillis()); result.Err != nil { 1751 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 1752 } 1753 if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId2, channel.Id, model.GetMillis()); result.Err != nil { 1754 mlog.Warn(fmt.Sprintf("Failed to update ChannelMemberHistory table %v", result.Err)) 1755 } 1756 1757 return channel, nil 1758 } 1759 return nil, model.NewAppError("GetOrCreateDMChannel", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message, result.Err.StatusCode) 1760 } 1761 return result.Data.(*model.Channel), nil 1762 } 1763 1764 func (a *App) ToggleMuteChannel(channelId string, userId string) *model.ChannelMember { 1765 result := <-a.Srv.Store.Channel().GetMember(channelId, userId) 1766 1767 if result.Err != nil { 1768 return nil 1769 } 1770 1771 member := result.Data.(*model.ChannelMember) 1772 1773 if member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_NOTIFY_MENTION { 1774 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = model.CHANNEL_MARK_UNREAD_ALL 1775 } else { 1776 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = model.CHANNEL_NOTIFY_MENTION 1777 } 1778 1779 a.Srv.Store.Channel().UpdateMember(member) 1780 return member 1781 } 1782 1783 func (a *App) FillInChannelProps(channel *model.Channel) *model.AppError { 1784 return a.FillInChannelsProps(&model.ChannelList{channel}) 1785 } 1786 1787 func (a *App) FillInChannelsProps(channelList *model.ChannelList) *model.AppError { 1788 // Group the channels by team and call GetChannelsByNames just once per team. 1789 channelsByTeam := make(map[string]model.ChannelList) 1790 for _, channel := range *channelList { 1791 channelsByTeam[channel.TeamId] = append(channelsByTeam[channel.TeamId], channel) 1792 } 1793 1794 for teamId, channelList := range channelsByTeam { 1795 allChannelMentions := make(map[string]bool) 1796 channelMentions := make(map[*model.Channel][]string, len(channelList)) 1797 1798 // Collect mentions across the channels so as to query just once for this team. 1799 for _, channel := range channelList { 1800 channelMentions[channel] = model.ChannelMentions(channel.Header) 1801 1802 for _, channelMention := range channelMentions[channel] { 1803 allChannelMentions[channelMention] = true 1804 } 1805 } 1806 1807 allChannelMentionNames := make([]string, 0, len(allChannelMentions)) 1808 for channelName := range allChannelMentions { 1809 allChannelMentionNames = append(allChannelMentionNames, channelName) 1810 } 1811 1812 if len(allChannelMentionNames) > 0 { 1813 mentionedChannels, err := a.GetChannelsByNames(allChannelMentionNames, teamId) 1814 if err != nil { 1815 return err 1816 } 1817 1818 mentionedChannelsByName := make(map[string]*model.Channel) 1819 for _, channel := range mentionedChannels { 1820 mentionedChannelsByName[channel.Name] = channel 1821 } 1822 1823 for _, channel := range channelList { 1824 channelMentionsProp := make(map[string]interface{}, len(channelMentions[channel])) 1825 for _, channelMention := range channelMentions[channel] { 1826 if mentioned, ok := mentionedChannelsByName[channelMention]; ok { 1827 if mentioned.Type == model.CHANNEL_OPEN { 1828 channelMentionsProp[mentioned.Name] = map[string]interface{}{ 1829 "display_name": mentioned.DisplayName, 1830 } 1831 } 1832 } 1833 } 1834 1835 if len(channelMentionsProp) > 0 { 1836 channel.AddProp("channel_mentions", channelMentionsProp) 1837 } else if channel.Props != nil { 1838 delete(channel.Props, "channel_mentions") 1839 } 1840 } 1841 } 1842 } 1843 1844 return nil 1845 }