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  }