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