github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/channel.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"fmt"
    10  	"net/http"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/mattermost/mattermost-server/v5/mlog"
    15  	"github.com/mattermost/mattermost-server/v5/model"
    16  	"github.com/mattermost/mattermost-server/v5/plugin"
    17  	"github.com/mattermost/mattermost-server/v5/store"
    18  	"github.com/mattermost/mattermost-server/v5/utils"
    19  )
    20  
    21  // CreateDefaultChannels creates channels in the given team for each channel returned by (*App).DefaultChannelNames.
    22  //
    23  func (a *App) CreateDefaultChannels(teamID string) ([]*model.Channel, *model.AppError) {
    24  	displayNames := map[string]string{
    25  		"town-square": utils.T("api.channel.create_default_channels.town_square"),
    26  		"off-topic":   utils.T("api.channel.create_default_channels.off_topic"),
    27  	}
    28  	channels := []*model.Channel{}
    29  	defaultChannelNames := a.DefaultChannelNames()
    30  	for _, name := range defaultChannelNames {
    31  		displayName := utils.TDefault(displayNames[name], name)
    32  		channel := &model.Channel{DisplayName: displayName, Name: name, Type: model.CHANNEL_OPEN, TeamId: teamID}
    33  		if _, err := a.CreateChannel(channel, false); err != nil {
    34  			return nil, err
    35  		}
    36  		channels = append(channels, channel)
    37  	}
    38  	return channels, nil
    39  }
    40  
    41  // DefaultChannelNames returns the list of system-wide default channel names.
    42  //
    43  // By default the list will be (not necessarily in this order):
    44  //	['town-square', 'off-topic']
    45  // However, if TeamSettings.ExperimentalDefaultChannels contains a list of channels then that list will replace
    46  // 'off-topic' and be included in the return results in addition to 'town-square'. For example:
    47  //	['town-square', 'game-of-thrones', 'wow']
    48  //
    49  func (a *App) DefaultChannelNames() []string {
    50  	names := []string{"town-square"}
    51  
    52  	if len(a.Config().TeamSettings.ExperimentalDefaultChannels) == 0 {
    53  		names = append(names, "off-topic")
    54  	} else {
    55  		seenChannels := map[string]bool{"town-square": true}
    56  		for _, channelName := range a.Config().TeamSettings.ExperimentalDefaultChannels {
    57  			if !seenChannels[channelName] {
    58  				names = append(names, channelName)
    59  				seenChannels[channelName] = true
    60  			}
    61  		}
    62  	}
    63  
    64  	return names
    65  }
    66  
    67  func (a *App) JoinDefaultChannels(teamID string, user *model.User, shouldBeAdmin bool, userRequestorId string) *model.AppError {
    68  	var requestor *model.User
    69  	var nErr error
    70  	if userRequestorId != "" {
    71  		requestor, nErr = a.Srv().Store.User().Get(context.Background(), userRequestorId)
    72  		if nErr != nil {
    73  			var nfErr *store.ErrNotFound
    74  			switch {
    75  			case errors.As(nErr, &nfErr):
    76  				return model.NewAppError("JoinDefaultChannels", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
    77  			default:
    78  				return model.NewAppError("JoinDefaultChannels", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
    79  			}
    80  		}
    81  	}
    82  
    83  	var err *model.AppError
    84  	for _, channelName := range a.DefaultChannelNames() {
    85  		channel, channelErr := a.Srv().Store.Channel().GetByName(teamID, channelName, true)
    86  		if channelErr != nil {
    87  			var nfErr *store.ErrNotFound
    88  			switch {
    89  			case errors.As(err, &nfErr):
    90  				err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
    91  			default:
    92  				err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.existing.app_error", nil, channelErr.Error(), http.StatusInternalServerError)
    93  			}
    94  			continue
    95  		}
    96  
    97  		if channel.Type != model.CHANNEL_OPEN {
    98  			continue
    99  		}
   100  
   101  		cm := &model.ChannelMember{
   102  			ChannelId:   channel.Id,
   103  			UserId:      user.Id,
   104  			SchemeGuest: user.IsGuest(),
   105  			SchemeUser:  !user.IsGuest(),
   106  			SchemeAdmin: shouldBeAdmin,
   107  			NotifyProps: model.GetDefaultChannelNotifyProps(),
   108  		}
   109  
   110  		_, nErr = a.Srv().Store.Channel().SaveMember(cm)
   111  		if histErr := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); histErr != nil {
   112  			return model.NewAppError("JoinDefaultChannels", "app.channel_member_history.log_join_event.internal_error", nil, histErr.Error(), http.StatusInternalServerError)
   113  		}
   114  
   115  		if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
   116  			if aErr := a.postJoinMessageForDefaultChannel(user, requestor, channel); aErr != nil {
   117  				mlog.Warn("Failed to post join/leave message", mlog.Err(aErr))
   118  			}
   119  		}
   120  
   121  		a.invalidateCacheForChannelMembers(channel.Id)
   122  
   123  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil)
   124  		message.Add("user_id", user.Id)
   125  		message.Add("team_id", channel.TeamId)
   126  		a.Publish(message)
   127  
   128  	}
   129  
   130  	if nErr != nil {
   131  		var appErr *model.AppError
   132  		var cErr *store.ErrConflict
   133  		switch {
   134  		case errors.As(nErr, &cErr):
   135  			if cErr.Resource == "ChannelMembers" {
   136  				return model.NewAppError("JoinDefaultChannels", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest)
   137  			}
   138  		case errors.As(nErr, &appErr):
   139  			return appErr
   140  		default:
   141  			return model.NewAppError("JoinDefaultChannels", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   142  		}
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  func (a *App) postJoinMessageForDefaultChannel(user *model.User, requestor *model.User, channel *model.Channel) *model.AppError {
   149  	if channel.Name == model.DEFAULT_CHANNEL {
   150  		if requestor == nil {
   151  			if err := a.postJoinTeamMessage(user, channel); err != nil {
   152  				return err
   153  			}
   154  		} else {
   155  			if err := a.postAddToTeamMessage(requestor, user, channel, ""); err != nil {
   156  				return err
   157  			}
   158  		}
   159  	} else {
   160  		if requestor == nil {
   161  			if err := a.postJoinChannelMessage(user, channel); err != nil {
   162  				return err
   163  			}
   164  		} else {
   165  			if err := a.PostAddToChannelMessage(requestor, user, channel, ""); err != nil {
   166  				return err
   167  			}
   168  		}
   169  	}
   170  
   171  	return nil
   172  }
   173  
   174  func (a *App) CreateChannelWithUser(channel *model.Channel, userID string) (*model.Channel, *model.AppError) {
   175  	if channel.IsGroupOrDirect() {
   176  		return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.direct_channel.app_error", nil, "", http.StatusBadRequest)
   177  	}
   178  
   179  	if channel.TeamId == "" {
   180  		return nil, model.NewAppError("CreateChannelWithUser", "app.channel.create_channel.no_team_id.app_error", nil, "", http.StatusBadRequest)
   181  	}
   182  
   183  	// Get total number of channels on current team
   184  	count, err := a.GetNumberOfChannelsOnTeam(channel.TeamId)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	if int64(count+1) > *a.Config().TeamSettings.MaxChannelsPerTeam {
   190  		return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.max_channel_limit.app_error", map[string]interface{}{"MaxChannelsPerTeam": *a.Config().TeamSettings.MaxChannelsPerTeam}, "", http.StatusBadRequest)
   191  	}
   192  
   193  	channel.CreatorId = userID
   194  
   195  	rchannel, err := a.CreateChannel(channel, true)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	var user *model.User
   201  	if user, err = a.GetUser(userID); err != nil {
   202  		return nil, err
   203  	}
   204  
   205  	a.postJoinChannelMessage(user, channel)
   206  
   207  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CREATED, "", "", userID, nil)
   208  	message.Add("channel_id", channel.Id)
   209  	message.Add("team_id", channel.TeamId)
   210  	a.Publish(message)
   211  
   212  	return rchannel, nil
   213  }
   214  
   215  // RenameChannel is used to rename the channel Name and the DisplayName fields
   216  func (a *App) RenameChannel(channel *model.Channel, newChannelName string, newDisplayName string) (*model.Channel, *model.AppError) {
   217  	if channel.Type == model.CHANNEL_DIRECT {
   218  		return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_direct_messages.app_error", nil, "", http.StatusBadRequest)
   219  	}
   220  
   221  	if channel.Type == model.CHANNEL_GROUP {
   222  		return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_group_messages.app_error", nil, "", http.StatusBadRequest)
   223  	}
   224  
   225  	channel.Name = newChannelName
   226  	if newDisplayName != "" {
   227  		channel.DisplayName = newDisplayName
   228  	}
   229  
   230  	newChannel, err := a.UpdateChannel(channel)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	return newChannel, nil
   236  }
   237  
   238  func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) {
   239  	channel.DisplayName = strings.TrimSpace(channel.DisplayName)
   240  	sc, nErr := a.Srv().Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam)
   241  	if nErr != nil {
   242  		var invErr *store.ErrInvalidInput
   243  		var cErr *store.ErrConflict
   244  		var ltErr *store.ErrLimitExceeded
   245  		var appErr *model.AppError
   246  		switch {
   247  		case errors.As(nErr, &invErr):
   248  			switch {
   249  			case invErr.Entity == "Channel" && invErr.Field == "DeleteAt":
   250  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   251  			case invErr.Entity == "Channel" && invErr.Field == "Type":
   252  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest)
   253  			case invErr.Entity == "Channel" && invErr.Field == "Id":
   254  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest)
   255  			}
   256  		case errors.As(nErr, &cErr):
   257  			return sc, model.NewAppError("CreateChannel", store.ChannelExistsError, nil, cErr.Error(), http.StatusBadRequest)
   258  		case errors.As(nErr, &ltErr):
   259  			return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest)
   260  		case errors.As(nErr, &appErr): // in case we haven't converted to plain error.
   261  			return nil, appErr
   262  		default: // last fallback in case it doesn't map to an existing app error.
   263  			return nil, model.NewAppError("CreateChannel", "app.channel.create_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   264  		}
   265  	}
   266  
   267  	if addMember {
   268  		user, nErr := a.Srv().Store.User().Get(context.Background(), channel.CreatorId)
   269  		if nErr != nil {
   270  			var nfErr *store.ErrNotFound
   271  			switch {
   272  			case errors.As(nErr, &nfErr):
   273  				return nil, model.NewAppError("CreateChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
   274  			default:
   275  				return nil, model.NewAppError("CreateChannel", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   276  			}
   277  		}
   278  
   279  		cm := &model.ChannelMember{
   280  			ChannelId:   sc.Id,
   281  			UserId:      user.Id,
   282  			SchemeGuest: user.IsGuest(),
   283  			SchemeUser:  !user.IsGuest(),
   284  			SchemeAdmin: true,
   285  			NotifyProps: model.GetDefaultChannelNotifyProps(),
   286  		}
   287  
   288  		if _, nErr := a.Srv().Store.Channel().SaveMember(cm); nErr != nil {
   289  			var appErr *model.AppError
   290  			var cErr *store.ErrConflict
   291  			switch {
   292  			case errors.As(nErr, &cErr):
   293  				switch cErr.Resource {
   294  				case "ChannelMembers":
   295  					return nil, model.NewAppError("CreateChannel", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest)
   296  				}
   297  			case errors.As(nErr, &appErr):
   298  				return nil, appErr
   299  			default:
   300  				return nil, model.NewAppError("CreateChannel", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   301  			}
   302  		}
   303  
   304  		if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(channel.CreatorId, sc.Id, model.GetMillis()); err != nil {
   305  			return nil, model.NewAppError("CreateChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError)
   306  		}
   307  
   308  		a.InvalidateCacheForUser(channel.CreatorId)
   309  	}
   310  
   311  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
   312  		a.Srv().Go(func() {
   313  			pluginContext := a.PluginContext()
   314  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
   315  				hooks.ChannelHasBeenCreated(pluginContext, sc)
   316  				return true
   317  			}, plugin.ChannelHasBeenCreatedId)
   318  		})
   319  	}
   320  
   321  	return sc, nil
   322  }
   323  
   324  func (a *App) GetOrCreateDirectChannel(userID, otherUserID string) (*model.Channel, *model.AppError) {
   325  	channel, nErr := a.getDirectChannel(userID, otherUserID)
   326  	if nErr != nil {
   327  		return nil, nErr
   328  	}
   329  
   330  	if channel != nil {
   331  		return channel, nil
   332  	}
   333  
   334  	channel, err := a.createDirectChannel(userID, otherUserID)
   335  	if err != nil {
   336  		if err.Id == store.ChannelExistsError {
   337  			return channel, nil
   338  		}
   339  		return nil, err
   340  	}
   341  
   342  	a.WaitForChannelMembership(channel.Id, userID)
   343  	a.handleCreationEvent(userID, otherUserID, channel)
   344  	return channel, nil
   345  }
   346  
   347  func (a *App) getOrCreateDirectChannelWithUser(user, otherUser *model.User) (*model.Channel, *model.AppError) {
   348  	channel, nErr := a.getDirectChannel(user.Id, otherUser.Id)
   349  	if nErr != nil {
   350  		return nil, nErr
   351  	}
   352  
   353  	if channel != nil {
   354  		return channel, nil
   355  	}
   356  
   357  	channel, err := a.createDirectChannelWithUser(user, otherUser)
   358  	if err != nil {
   359  		if err.Id == store.ChannelExistsError {
   360  			return channel, nil
   361  		}
   362  		return nil, err
   363  	}
   364  
   365  	a.WaitForChannelMembership(channel.Id, user.Id)
   366  	a.handleCreationEvent(user.Id, otherUser.Id, channel)
   367  	return channel, nil
   368  }
   369  
   370  func (a *App) handleCreationEvent(userID, otherUserID string, channel *model.Channel) {
   371  	a.InvalidateCacheForUser(userID)
   372  	a.InvalidateCacheForUser(otherUserID)
   373  
   374  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
   375  		a.Srv().Go(func() {
   376  			pluginContext := a.PluginContext()
   377  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
   378  				hooks.ChannelHasBeenCreated(pluginContext, channel)
   379  				return true
   380  			}, plugin.ChannelHasBeenCreatedId)
   381  		})
   382  	}
   383  
   384  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil)
   385  	message.Add("teammate_id", otherUserID)
   386  	a.Publish(message)
   387  }
   388  
   389  func (a *App) createDirectChannel(userID, otherUserID string) (*model.Channel, *model.AppError) {
   390  	users, err := a.Srv().Store.User().GetMany(context.Background(), []string{userID, otherUserID})
   391  	if err != nil {
   392  		return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, err.Error(), http.StatusBadRequest)
   393  	}
   394  
   395  	if len(users) == 0 {
   396  		return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, fmt.Sprintf("No users found for ids: %s. %s", userID, otherUserID), http.StatusBadRequest)
   397  	}
   398  
   399  	// We are doing this because we allow a user to create a direct channel with themselves
   400  	if userID == otherUserID {
   401  		users = append(users, users[0])
   402  	}
   403  
   404  	// After we counted for direct channels with the same user, if we do not have two users then we failed to find one
   405  	if len(users) != 2 {
   406  		return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, fmt.Sprintf("No users found for ids: %s. %s", userID, otherUserID), http.StatusBadRequest)
   407  	}
   408  
   409  	// The potential swap dance bellow is necessary in order to guarantee determinism when creating a direct channel.
   410  	// When we query the database for some given user ids, the database result is not deterministic, meaning we can get
   411  	// the same results but in different order. In order to conform the contract of Channel.CreateDirectChannel method
   412  	// bellow we need to identify which user is who.
   413  	user := users[0]
   414  	otherUser := users[1]
   415  	if user.Id != userID {
   416  		user = users[1]
   417  		otherUser = users[0]
   418  	}
   419  	return a.createDirectChannelWithUser(user, otherUser)
   420  }
   421  
   422  func (a *App) createDirectChannelWithUser(user, otherUser *model.User) (*model.Channel, *model.AppError) {
   423  	channel, nErr := a.Srv().Store.Channel().CreateDirectChannel(user, otherUser)
   424  	if nErr != nil {
   425  		var invErr *store.ErrInvalidInput
   426  		var cErr *store.ErrConflict
   427  		var ltErr *store.ErrLimitExceeded
   428  		var appErr *model.AppError
   429  		switch {
   430  		case errors.As(nErr, &invErr):
   431  			switch {
   432  			case invErr.Entity == "Channel" && invErr.Field == "DeleteAt":
   433  				return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   434  			case invErr.Entity == "Channel" && invErr.Field == "Type":
   435  				return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest)
   436  			case invErr.Entity == "Channel" && invErr.Field == "Id":
   437  				return nil, model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest)
   438  			}
   439  		case errors.As(nErr, &cErr):
   440  			switch cErr.Resource {
   441  			case "Channel":
   442  				return channel, model.NewAppError("createDirectChannelWithUser", store.ChannelExistsError, nil, cErr.Error(), http.StatusBadRequest)
   443  			case "ChannelMembers":
   444  				return nil, model.NewAppError("createDirectChannelWithUser", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest)
   445  			}
   446  		case errors.As(nErr, &ltErr):
   447  			return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest)
   448  		case errors.As(nErr, &appErr): // in case we haven't converted to plain error.
   449  			return nil, appErr
   450  		default: // last fallback in case it doesn't map to an existing app error.
   451  			return nil, model.NewAppError("createDirectChannelWithUser", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   452  		}
   453  	}
   454  
   455  	if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil {
   456  		return nil, model.NewAppError("createDirectChannelWithUser", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError)
   457  	}
   458  	if user.Id != otherUser.Id {
   459  		if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(otherUser.Id, channel.Id, model.GetMillis()); err != nil {
   460  			return nil, model.NewAppError("createDirectChannelWithUser", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError)
   461  		}
   462  	}
   463  
   464  	return channel, nil
   465  }
   466  
   467  func (a *App) WaitForChannelMembership(channelId string, userID string) {
   468  	if len(a.Config().SqlSettings.DataSourceReplicas) == 0 {
   469  		return
   470  	}
   471  
   472  	now := model.GetMillis()
   473  
   474  	for model.GetMillis()-now < 12000 {
   475  
   476  		time.Sleep(100 * time.Millisecond)
   477  
   478  		_, err := a.Srv().Store.Channel().GetMember(channelId, userID)
   479  
   480  		// If the membership was found then return
   481  		if err == nil {
   482  			return
   483  		}
   484  
   485  		// If we received an error, but it wasn't a missing channel member then return
   486  		var nfErr *store.ErrNotFound
   487  		if !errors.As(err, &nfErr) {
   488  			return
   489  		}
   490  	}
   491  
   492  	mlog.Error("WaitForChannelMembership giving up", mlog.String("channel_id", channelId), mlog.String("user_id", userID))
   493  }
   494  
   495  func (a *App) CreateGroupChannel(userIDs []string, creatorId string) (*model.Channel, *model.AppError) {
   496  	channel, err := a.createGroupChannel(userIDs)
   497  	if err != nil {
   498  		if err.Id == store.ChannelExistsError {
   499  			return channel, nil
   500  		}
   501  		return nil, err
   502  	}
   503  
   504  	for _, userID := range userIDs {
   505  		if userID == creatorId {
   506  			a.WaitForChannelMembership(channel.Id, creatorId)
   507  		}
   508  
   509  		a.InvalidateCacheForUser(userID)
   510  	}
   511  
   512  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_GROUP_ADDED, "", channel.Id, "", nil)
   513  	message.Add("teammate_ids", model.ArrayToJson(userIDs))
   514  	a.Publish(message)
   515  
   516  	return channel, nil
   517  }
   518  
   519  func (a *App) createGroupChannel(userIDs []string) (*model.Channel, *model.AppError) {
   520  	if len(userIDs) > model.CHANNEL_GROUP_MAX_USERS || len(userIDs) < model.CHANNEL_GROUP_MIN_USERS {
   521  		return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest)
   522  	}
   523  
   524  	users, err := a.Srv().Store.User().GetProfileByIds(context.Background(), userIDs, nil, true)
   525  	if err != nil {
   526  		return nil, model.NewAppError("createGroupChannel", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   527  	}
   528  
   529  	if len(users) != len(userIDs) {
   530  		return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIDs), http.StatusBadRequest)
   531  	}
   532  
   533  	group := &model.Channel{
   534  		Name:        model.GetGroupNameFromUserIds(userIDs),
   535  		DisplayName: model.GetGroupDisplayNameFromUsers(users, true),
   536  		Type:        model.CHANNEL_GROUP,
   537  	}
   538  
   539  	channel, nErr := a.Srv().Store.Channel().Save(group, *a.Config().TeamSettings.MaxChannelsPerTeam)
   540  	if nErr != nil {
   541  		var invErr *store.ErrInvalidInput
   542  		var cErr *store.ErrConflict
   543  		var ltErr *store.ErrLimitExceeded
   544  		var appErr *model.AppError
   545  		switch {
   546  		case errors.As(nErr, &invErr):
   547  			switch {
   548  			case invErr.Entity == "Channel" && invErr.Field == "DeleteAt":
   549  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   550  			case invErr.Entity == "Channel" && invErr.Field == "Type":
   551  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest)
   552  			case invErr.Entity == "Channel" && invErr.Field == "Id":
   553  				return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest)
   554  			}
   555  		case errors.As(nErr, &cErr):
   556  			return channel, model.NewAppError("CreateChannel", store.ChannelExistsError, nil, cErr.Error(), http.StatusBadRequest)
   557  		case errors.As(nErr, &ltErr):
   558  			return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest)
   559  		case errors.As(nErr, &appErr): // in case we haven't converted to plain error.
   560  			return nil, appErr
   561  		default: // last fallback in case it doesn't map to an existing app error.
   562  			return nil, model.NewAppError("CreateChannel", "app.channel.create_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   563  		}
   564  	}
   565  
   566  	for _, user := range users {
   567  		cm := &model.ChannelMember{
   568  			UserId:      user.Id,
   569  			ChannelId:   group.Id,
   570  			NotifyProps: model.GetDefaultChannelNotifyProps(),
   571  			SchemeGuest: user.IsGuest(),
   572  			SchemeUser:  !user.IsGuest(),
   573  		}
   574  
   575  		if _, nErr = a.Srv().Store.Channel().SaveMember(cm); nErr != nil {
   576  			var appErr *model.AppError
   577  			var cErr *store.ErrConflict
   578  			switch {
   579  			case errors.As(nErr, &cErr):
   580  				switch cErr.Resource {
   581  				case "ChannelMembers":
   582  					return nil, model.NewAppError("createGroupChannel", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest)
   583  				}
   584  			case errors.As(nErr, &appErr):
   585  				return nil, appErr
   586  			default:
   587  				return nil, model.NewAppError("createGroupChannel", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
   588  			}
   589  		}
   590  		if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil {
   591  			return nil, model.NewAppError("createGroupChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError)
   592  		}
   593  	}
   594  
   595  	return channel, nil
   596  }
   597  
   598  func (a *App) GetGroupChannel(userIDs []string) (*model.Channel, *model.AppError) {
   599  	if len(userIDs) > model.CHANNEL_GROUP_MAX_USERS || len(userIDs) < model.CHANNEL_GROUP_MIN_USERS {
   600  		return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest)
   601  	}
   602  
   603  	users, err := a.Srv().Store.User().GetProfileByIds(context.Background(), userIDs, nil, true)
   604  	if err != nil {
   605  		return nil, model.NewAppError("GetGroupChannel", "app.user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   606  	}
   607  
   608  	if len(users) != len(userIDs) {
   609  		return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIDs), http.StatusBadRequest)
   610  	}
   611  
   612  	channel, appErr := a.GetChannelByName(model.GetGroupNameFromUserIds(userIDs), "", true)
   613  	if appErr != nil {
   614  		return nil, appErr
   615  	}
   616  
   617  	return channel, nil
   618  }
   619  
   620  // UpdateChannel updates a given channel by its Id. It also publishes the CHANNEL_UPDATED event.
   621  func (a *App) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
   622  	_, err := a.Srv().Store.Channel().Update(channel)
   623  	if err != nil {
   624  		var appErr *model.AppError
   625  		var invErr *store.ErrInvalidInput
   626  		switch {
   627  		case errors.As(err, &invErr):
   628  			return nil, model.NewAppError("UpdateChannel", "app.channel.update.bad_id", nil, invErr.Error(), http.StatusBadRequest)
   629  		case errors.As(err, &appErr):
   630  			return nil, appErr
   631  		default:
   632  			return nil, model.NewAppError("UpdateChannel", "app.channel.update_channel.internal_error", nil, err.Error(), http.StatusInternalServerError)
   633  		}
   634  	}
   635  
   636  	a.invalidateCacheForChannel(channel)
   637  
   638  	messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_UPDATED, "", channel.Id, "", nil)
   639  	messageWs.Add("channel", channel.ToJson())
   640  	a.Publish(messageWs)
   641  
   642  	return channel, nil
   643  }
   644  
   645  // CreateChannelScheme creates a new Scheme of scope channel and assigns it to the channel.
   646  func (a *App) CreateChannelScheme(channel *model.Channel) (*model.Scheme, *model.AppError) {
   647  	scheme, err := a.CreateScheme(&model.Scheme{
   648  		Name:        model.NewId(),
   649  		DisplayName: model.NewId(),
   650  		Scope:       model.SCHEME_SCOPE_CHANNEL,
   651  	})
   652  	if err != nil {
   653  		return nil, err
   654  	}
   655  
   656  	channel.SchemeId = &scheme.Id
   657  	if _, err := a.UpdateChannelScheme(channel); err != nil {
   658  		return nil, err
   659  	}
   660  	return scheme, nil
   661  }
   662  
   663  // DeleteChannelScheme deletes a channels scheme and sets its SchemeId to nil.
   664  func (a *App) DeleteChannelScheme(channel *model.Channel) (*model.Channel, *model.AppError) {
   665  	if channel.SchemeId != nil && *channel.SchemeId != "" {
   666  		if _, err := a.DeleteScheme(*channel.SchemeId); err != nil {
   667  			return nil, err
   668  		}
   669  	}
   670  	channel.SchemeId = nil
   671  	return a.UpdateChannelScheme(channel)
   672  }
   673  
   674  // UpdateChannelScheme saves the new SchemeId of the channel passed.
   675  func (a *App) UpdateChannelScheme(channel *model.Channel) (*model.Channel, *model.AppError) {
   676  	var oldChannel *model.Channel
   677  	var err *model.AppError
   678  	if oldChannel, err = a.GetChannel(channel.Id); err != nil {
   679  		return nil, err
   680  	}
   681  
   682  	oldChannel.SchemeId = channel.SchemeId
   683  	return a.UpdateChannel(oldChannel)
   684  }
   685  
   686  func (a *App) UpdateChannelPrivacy(oldChannel *model.Channel, user *model.User) (*model.Channel, *model.AppError) {
   687  	channel, err := a.UpdateChannel(oldChannel)
   688  	if err != nil {
   689  		return channel, err
   690  	}
   691  
   692  	if err := a.postChannelPrivacyMessage(user, channel); err != nil {
   693  		if channel.Type == model.CHANNEL_OPEN {
   694  			channel.Type = model.CHANNEL_PRIVATE
   695  		} else {
   696  			channel.Type = model.CHANNEL_OPEN
   697  		}
   698  		// revert to previous channel privacy
   699  		a.UpdateChannel(channel)
   700  		return channel, err
   701  	}
   702  
   703  	a.invalidateCacheForChannel(channel)
   704  
   705  	messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CONVERTED, channel.TeamId, "", "", nil)
   706  	messageWs.Add("channel_id", channel.Id)
   707  	a.Publish(messageWs)
   708  
   709  	return channel, nil
   710  }
   711  
   712  func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel) *model.AppError {
   713  	message := (map[string]string{
   714  		model.CHANNEL_OPEN:    utils.T("api.channel.change_channel_privacy.private_to_public"),
   715  		model.CHANNEL_PRIVATE: utils.T("api.channel.change_channel_privacy.public_to_private"),
   716  	})[channel.Type]
   717  	post := &model.Post{
   718  		ChannelId: channel.Id,
   719  		Message:   message,
   720  		Type:      model.POST_CHANGE_CHANNEL_PRIVACY,
   721  		UserId:    user.Id,
   722  		Props: model.StringInterface{
   723  			"username": user.Username,
   724  		},
   725  	}
   726  
   727  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
   728  		return model.NewAppError("postChannelPrivacyMessage", "api.channel.post_channel_privacy_message.error", nil, err.Error(), http.StatusInternalServerError)
   729  	}
   730  
   731  	return nil
   732  }
   733  
   734  func (a *App) RestoreChannel(channel *model.Channel, userID string) (*model.Channel, *model.AppError) {
   735  	if channel.DeleteAt == 0 {
   736  		return nil, model.NewAppError("restoreChannel", "api.channel.restore_channel.restored.app_error", nil, "", http.StatusBadRequest)
   737  	}
   738  
   739  	if err := a.Srv().Store.Channel().Restore(channel.Id, model.GetMillis()); err != nil {
   740  		return nil, model.NewAppError("RestoreChannel", "app.channel.restore.app_error", nil, err.Error(), http.StatusInternalServerError)
   741  	}
   742  	channel.DeleteAt = 0
   743  	a.invalidateCacheForChannel(channel)
   744  
   745  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_RESTORED, channel.TeamId, "", "", nil)
   746  	message.Add("channel_id", channel.Id)
   747  	a.Publish(message)
   748  
   749  	user, nErr := a.Srv().Store.User().Get(context.Background(), userID)
   750  	if nErr != nil {
   751  		var nfErr *store.ErrNotFound
   752  		switch {
   753  		case errors.As(nErr, &nfErr):
   754  			return nil, model.NewAppError("RestoreChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
   755  		default:
   756  			return nil, model.NewAppError("RestoreChannel", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   757  		}
   758  	}
   759  
   760  	if user != nil {
   761  		T := utils.GetUserTranslations(user.Locale)
   762  
   763  		post := &model.Post{
   764  			ChannelId: channel.Id,
   765  			Message:   T("api.channel.restore_channel.unarchived", map[string]interface{}{"Username": user.Username}),
   766  			Type:      model.POST_CHANNEL_RESTORED,
   767  			UserId:    userID,
   768  			Props: model.StringInterface{
   769  				"username": user.Username,
   770  			},
   771  		}
   772  
   773  		if _, err := a.CreatePost(post, channel, false, true); err != nil {
   774  			mlog.Warn("Failed to post unarchive message", mlog.Err(err))
   775  		}
   776  	}
   777  
   778  	return channel, nil
   779  }
   780  
   781  func (a *App) PatchChannel(channel *model.Channel, patch *model.ChannelPatch, userID string) (*model.Channel, *model.AppError) {
   782  	oldChannelDisplayName := channel.DisplayName
   783  	oldChannelHeader := channel.Header
   784  	oldChannelPurpose := channel.Purpose
   785  
   786  	channel.Patch(patch)
   787  	channel, err := a.UpdateChannel(channel)
   788  	if err != nil {
   789  		return nil, err
   790  	}
   791  
   792  	if oldChannelDisplayName != channel.DisplayName {
   793  		if err = a.PostUpdateChannelDisplayNameMessage(userID, channel, oldChannelDisplayName, channel.DisplayName); err != nil {
   794  			mlog.Warn(err.Error())
   795  		}
   796  	}
   797  
   798  	if channel.Header != oldChannelHeader {
   799  		if err = a.PostUpdateChannelHeaderMessage(userID, channel, oldChannelHeader, channel.Header); err != nil {
   800  			mlog.Warn(err.Error())
   801  		}
   802  	}
   803  
   804  	if channel.Purpose != oldChannelPurpose {
   805  		if err = a.PostUpdateChannelPurposeMessage(userID, channel, oldChannelPurpose, channel.Purpose); err != nil {
   806  			mlog.Warn(err.Error())
   807  		}
   808  	}
   809  
   810  	return channel, nil
   811  }
   812  
   813  // GetSchemeRolesForChannel Checks if a channel or its team has an override scheme for channel roles and returns the scheme roles or default channel roles.
   814  func (a *App) GetSchemeRolesForChannel(channelId string) (guestRoleName, userRoleName, adminRoleName string, err *model.AppError) {
   815  	channel, err := a.GetChannel(channelId)
   816  	if err != nil {
   817  		return
   818  	}
   819  
   820  	if channel.SchemeId != nil && *channel.SchemeId != "" {
   821  		var scheme *model.Scheme
   822  		scheme, err = a.GetScheme(*channel.SchemeId)
   823  		if err != nil {
   824  			return
   825  		}
   826  
   827  		guestRoleName = scheme.DefaultChannelGuestRole
   828  		userRoleName = scheme.DefaultChannelUserRole
   829  		adminRoleName = scheme.DefaultChannelAdminRole
   830  
   831  		return
   832  	}
   833  
   834  	return a.GetTeamSchemeChannelRoles(channel.TeamId)
   835  }
   836  
   837  // GetTeamSchemeChannelRoles Checks if a team has an override scheme and returns the scheme channel role names or default channel role names.
   838  func (a *App) GetTeamSchemeChannelRoles(teamID string) (guestRoleName, userRoleName, adminRoleName string, err *model.AppError) {
   839  	team, err := a.GetTeam(teamID)
   840  	if err != nil {
   841  		return
   842  	}
   843  
   844  	if team.SchemeId != nil && *team.SchemeId != "" {
   845  		var scheme *model.Scheme
   846  		scheme, err = a.GetScheme(*team.SchemeId)
   847  		if err != nil {
   848  			return
   849  		}
   850  
   851  		guestRoleName = scheme.DefaultChannelGuestRole
   852  		userRoleName = scheme.DefaultChannelUserRole
   853  		adminRoleName = scheme.DefaultChannelAdminRole
   854  	} else {
   855  		guestRoleName = model.CHANNEL_GUEST_ROLE_ID
   856  		userRoleName = model.CHANNEL_USER_ROLE_ID
   857  		adminRoleName = model.CHANNEL_ADMIN_ROLE_ID
   858  	}
   859  
   860  	return
   861  }
   862  
   863  // GetChannelModerationsForChannel Gets a channels ChannelModerations from either the higherScoped roles or from the channel scheme roles.
   864  func (a *App) GetChannelModerationsForChannel(channel *model.Channel) ([]*model.ChannelModeration, *model.AppError) {
   865  	guestRoleName, memberRoleName, _, err := a.GetSchemeRolesForChannel(channel.Id)
   866  	if err != nil {
   867  		return nil, err
   868  	}
   869  
   870  	memberRole, err := a.GetRoleByName(memberRoleName)
   871  	if err != nil {
   872  		return nil, err
   873  	}
   874  
   875  	var guestRole *model.Role
   876  	if guestRoleName != "" {
   877  		guestRole, err = a.GetRoleByName(guestRoleName)
   878  		if err != nil {
   879  			return nil, err
   880  		}
   881  	}
   882  
   883  	higherScopedGuestRoleName, higherScopedMemberRoleName, _, err := a.GetTeamSchemeChannelRoles(channel.TeamId)
   884  	if err != nil {
   885  		return nil, err
   886  	}
   887  	higherScopedMemberRole, err := a.GetRoleByName(higherScopedMemberRoleName)
   888  	if err != nil {
   889  		return nil, err
   890  	}
   891  
   892  	var higherScopedGuestRole *model.Role
   893  	if higherScopedGuestRoleName != "" {
   894  		higherScopedGuestRole, err = a.GetRoleByName(higherScopedGuestRoleName)
   895  		if err != nil {
   896  			return nil, err
   897  		}
   898  	}
   899  
   900  	return buildChannelModerations(channel.Type, memberRole, guestRole, higherScopedMemberRole, higherScopedGuestRole), nil
   901  }
   902  
   903  // PatchChannelModerationsForChannel Updates a channels scheme roles based on a given ChannelModerationPatch, if the permissions match the higher scoped role the scheme is deleted.
   904  func (a *App) PatchChannelModerationsForChannel(channel *model.Channel, channelModerationsPatch []*model.ChannelModerationPatch) ([]*model.ChannelModeration, *model.AppError) {
   905  	higherScopedGuestRoleName, higherScopedMemberRoleName, _, err := a.GetTeamSchemeChannelRoles(channel.TeamId)
   906  	if err != nil {
   907  		return nil, err
   908  	}
   909  
   910  	higherScopedMemberRole, err := a.GetRoleByName(higherScopedMemberRoleName)
   911  	if err != nil {
   912  		return nil, err
   913  	}
   914  
   915  	var higherScopedGuestRole *model.Role
   916  	if higherScopedGuestRoleName != "" {
   917  		higherScopedGuestRole, err = a.GetRoleByName(higherScopedGuestRoleName)
   918  		if err != nil {
   919  			return nil, err
   920  		}
   921  	}
   922  
   923  	higherScopedMemberPermissions := higherScopedMemberRole.GetChannelModeratedPermissions(channel.Type)
   924  
   925  	var higherScopedGuestPermissions map[string]bool
   926  	if higherScopedGuestRole != nil {
   927  		higherScopedGuestPermissions = higherScopedGuestRole.GetChannelModeratedPermissions(channel.Type)
   928  	}
   929  
   930  	for _, moderationPatch := range channelModerationsPatch {
   931  		if moderationPatch.Roles.Members != nil && *moderationPatch.Roles.Members && !higherScopedMemberPermissions[*moderationPatch.Name] {
   932  			return nil, &model.AppError{Message: "Cannot add a permission that is restricted by the team or system permission scheme"}
   933  		}
   934  		if moderationPatch.Roles.Guests != nil && *moderationPatch.Roles.Guests && !higherScopedGuestPermissions[*moderationPatch.Name] {
   935  			return nil, &model.AppError{Message: "Cannot add a permission that is restricted by the team or system permission scheme"}
   936  		}
   937  	}
   938  
   939  	var scheme *model.Scheme
   940  	// Channel has no scheme so create one
   941  	if channel.SchemeId == nil || *channel.SchemeId == "" {
   942  		scheme, err = a.CreateChannelScheme(channel)
   943  		if err != nil {
   944  			return nil, err
   945  		}
   946  
   947  		// Send a websocket event about this new role. The other new roles—member and guest—get emitted when they're updated.
   948  		var adminRole *model.Role
   949  		adminRole, err = a.GetRoleByName(scheme.DefaultChannelAdminRole)
   950  		if err != nil {
   951  			return nil, err
   952  		}
   953  		a.sendUpdatedRoleEvent(adminRole)
   954  
   955  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_SCHEME_UPDATED, "", channel.Id, "", nil)
   956  		a.Publish(message)
   957  		mlog.Info("Permission scheme created.", mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
   958  	} else {
   959  		scheme, err = a.GetScheme(*channel.SchemeId)
   960  		if err != nil {
   961  			return nil, err
   962  		}
   963  	}
   964  
   965  	guestRoleName := scheme.DefaultChannelGuestRole
   966  	memberRoleName := scheme.DefaultChannelUserRole
   967  	memberRole, err := a.GetRoleByName(memberRoleName)
   968  	if err != nil {
   969  		return nil, err
   970  	}
   971  
   972  	var guestRole *model.Role
   973  	if guestRoleName != "" {
   974  		guestRole, err = a.GetRoleByName(guestRoleName)
   975  		if err != nil {
   976  			return nil, err
   977  		}
   978  	}
   979  
   980  	memberRolePatch := memberRole.RolePatchFromChannelModerationsPatch(channelModerationsPatch, "members")
   981  	var guestRolePatch *model.RolePatch
   982  	if guestRole != nil {
   983  		guestRolePatch = guestRole.RolePatchFromChannelModerationsPatch(channelModerationsPatch, "guests")
   984  	}
   985  
   986  	for _, channelModerationPatch := range channelModerationsPatch {
   987  		permissionModified := *channelModerationPatch.Name
   988  		if channelModerationPatch.Roles.Guests != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(guestRole, guestRolePatch)) {
   989  			if *channelModerationPatch.Roles.Guests {
   990  				mlog.Info("Permission enabled for guests.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
   991  			} else {
   992  				mlog.Info("Permission disabled for guests.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
   993  			}
   994  		}
   995  
   996  		if channelModerationPatch.Roles.Members != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(memberRole, memberRolePatch)) {
   997  			if *channelModerationPatch.Roles.Members {
   998  				mlog.Info("Permission enabled for members.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
   999  			} else {
  1000  				mlog.Info("Permission disabled for members.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
  1001  			}
  1002  		}
  1003  	}
  1004  
  1005  	memberRolePermissionsUnmodified := len(model.ChannelModeratedPermissionsChangedByPatch(higherScopedMemberRole, memberRolePatch)) == 0
  1006  	guestRolePermissionsUnmodified := len(model.ChannelModeratedPermissionsChangedByPatch(higherScopedGuestRole, guestRolePatch)) == 0
  1007  	if memberRolePermissionsUnmodified && guestRolePermissionsUnmodified {
  1008  		// The channel scheme matches the permissions of its higherScoped scheme so delete the scheme
  1009  		if _, err = a.DeleteChannelScheme(channel); err != nil {
  1010  			return nil, err
  1011  		}
  1012  
  1013  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_SCHEME_UPDATED, "", channel.Id, "", nil)
  1014  		a.Publish(message)
  1015  
  1016  		memberRole = higherScopedMemberRole
  1017  		guestRole = higherScopedGuestRole
  1018  		mlog.Info("Permission scheme deleted.", mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
  1019  	} else {
  1020  		memberRole, err = a.PatchRole(memberRole, memberRolePatch)
  1021  		if err != nil {
  1022  			return nil, err
  1023  		}
  1024  		guestRole, err = a.PatchRole(guestRole, guestRolePatch)
  1025  		if err != nil {
  1026  			return nil, err
  1027  		}
  1028  	}
  1029  
  1030  	return buildChannelModerations(channel.Type, memberRole, guestRole, higherScopedMemberRole, higherScopedGuestRole), nil
  1031  }
  1032  
  1033  func buildChannelModerations(channelType string, memberRole *model.Role, guestRole *model.Role, higherScopedMemberRole *model.Role, higherScopedGuestRole *model.Role) []*model.ChannelModeration {
  1034  	var memberPermissions, guestPermissions, higherScopedMemberPermissions, higherScopedGuestPermissions map[string]bool
  1035  	if memberRole != nil {
  1036  		memberPermissions = memberRole.GetChannelModeratedPermissions(channelType)
  1037  	}
  1038  	if guestRole != nil {
  1039  		guestPermissions = guestRole.GetChannelModeratedPermissions(channelType)
  1040  	}
  1041  	if higherScopedMemberRole != nil {
  1042  		higherScopedMemberPermissions = higherScopedMemberRole.GetChannelModeratedPermissions(channelType)
  1043  	}
  1044  	if higherScopedGuestRole != nil {
  1045  		higherScopedGuestPermissions = higherScopedGuestRole.GetChannelModeratedPermissions(channelType)
  1046  	}
  1047  
  1048  	var channelModerations []*model.ChannelModeration
  1049  	for _, permissionKey := range model.ChannelModeratedPermissions {
  1050  		roles := &model.ChannelModeratedRoles{}
  1051  
  1052  		roles.Members = &model.ChannelModeratedRole{
  1053  			Value:   memberPermissions[permissionKey],
  1054  			Enabled: higherScopedMemberPermissions[permissionKey],
  1055  		}
  1056  
  1057  		if permissionKey == "manage_members" {
  1058  			roles.Guests = nil
  1059  		} else {
  1060  			roles.Guests = &model.ChannelModeratedRole{
  1061  				Value:   guestPermissions[permissionKey],
  1062  				Enabled: higherScopedGuestPermissions[permissionKey],
  1063  			}
  1064  		}
  1065  
  1066  		moderation := &model.ChannelModeration{
  1067  			Name:  permissionKey,
  1068  			Roles: roles,
  1069  		}
  1070  
  1071  		channelModerations = append(channelModerations, moderation)
  1072  	}
  1073  
  1074  	return channelModerations
  1075  }
  1076  
  1077  func (a *App) UpdateChannelMemberRoles(channelId string, userID string, newRoles string) (*model.ChannelMember, *model.AppError) {
  1078  	var member *model.ChannelMember
  1079  	var err *model.AppError
  1080  	if member, err = a.GetChannelMember(channelId, userID); err != nil {
  1081  		return nil, err
  1082  	}
  1083  
  1084  	schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForChannel(channelId)
  1085  	if err != nil {
  1086  		return nil, err
  1087  	}
  1088  
  1089  	prevSchemeGuestValue := member.SchemeGuest
  1090  
  1091  	var newExplicitRoles []string
  1092  	member.SchemeGuest = false
  1093  	member.SchemeUser = false
  1094  	member.SchemeAdmin = false
  1095  
  1096  	for _, roleName := range strings.Fields(newRoles) {
  1097  		var role *model.Role
  1098  		role, err = a.GetRoleByName(roleName)
  1099  		if err != nil {
  1100  			err.StatusCode = http.StatusBadRequest
  1101  			return nil, err
  1102  		}
  1103  
  1104  		if !role.SchemeManaged {
  1105  			// The role is not scheme-managed, so it's OK to apply it to the explicit roles field.
  1106  			newExplicitRoles = append(newExplicitRoles, roleName)
  1107  		} else {
  1108  			// The role is scheme-managed, so need to check if it is part of the scheme for this channel or not.
  1109  			switch roleName {
  1110  			case schemeAdminRole:
  1111  				member.SchemeAdmin = true
  1112  			case schemeUserRole:
  1113  				member.SchemeUser = true
  1114  			case schemeGuestRole:
  1115  				member.SchemeGuest = true
  1116  			default:
  1117  				// If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role.
  1118  				return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest)
  1119  			}
  1120  		}
  1121  	}
  1122  
  1123  	if member.SchemeUser && member.SchemeGuest {
  1124  		return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
  1125  	}
  1126  
  1127  	if prevSchemeGuestValue != member.SchemeGuest {
  1128  		return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest)
  1129  	}
  1130  
  1131  	member.ExplicitRoles = strings.Join(newExplicitRoles, " ")
  1132  
  1133  	return a.updateChannelMember(member)
  1134  }
  1135  
  1136  func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userID string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError) {
  1137  	member, err := a.GetChannelMember(channelId, userID)
  1138  	if err != nil {
  1139  		return nil, err
  1140  	}
  1141  
  1142  	member.SchemeAdmin = isSchemeAdmin
  1143  	member.SchemeUser = isSchemeUser
  1144  	member.SchemeGuest = isSchemeGuest
  1145  
  1146  	if member.SchemeUser && member.SchemeGuest {
  1147  		return nil, model.NewAppError("UpdateChannelMemberSchemeRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
  1148  	}
  1149  
  1150  	// 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.
  1151  	if err = a.IsPhase2MigrationCompleted(); err != nil {
  1152  		member.ExplicitRoles = RemoveRoles([]string{model.CHANNEL_GUEST_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID}, member.ExplicitRoles)
  1153  	}
  1154  
  1155  	return a.updateChannelMember(member)
  1156  }
  1157  
  1158  func (a *App) UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userID string) (*model.ChannelMember, *model.AppError) {
  1159  	var member *model.ChannelMember
  1160  	var err *model.AppError
  1161  	if member, err = a.GetChannelMember(channelId, userID); err != nil {
  1162  		return nil, err
  1163  	}
  1164  
  1165  	// update whichever notify properties have been provided, but don't change the others
  1166  	if markUnread, exists := data[model.MARK_UNREAD_NOTIFY_PROP]; exists {
  1167  		member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = markUnread
  1168  	}
  1169  
  1170  	if desktop, exists := data[model.DESKTOP_NOTIFY_PROP]; exists {
  1171  		member.NotifyProps[model.DESKTOP_NOTIFY_PROP] = desktop
  1172  	}
  1173  
  1174  	if email, exists := data[model.EMAIL_NOTIFY_PROP]; exists {
  1175  		member.NotifyProps[model.EMAIL_NOTIFY_PROP] = email
  1176  	}
  1177  
  1178  	if push, exists := data[model.PUSH_NOTIFY_PROP]; exists {
  1179  		member.NotifyProps[model.PUSH_NOTIFY_PROP] = push
  1180  	}
  1181  
  1182  	if ignoreChannelMentions, exists := data[model.IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP]; exists {
  1183  		member.NotifyProps[model.IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP] = ignoreChannelMentions
  1184  	}
  1185  
  1186  	member, err = a.updateChannelMember(member)
  1187  	if err != nil {
  1188  		return nil, err
  1189  	}
  1190  
  1191  	a.invalidateCacheForChannelMembersNotifyProps(member.ChannelId)
  1192  
  1193  	return member, nil
  1194  }
  1195  
  1196  func (a *App) updateChannelMember(member *model.ChannelMember) (*model.ChannelMember, *model.AppError) {
  1197  	member, nErr := a.Srv().Store.Channel().UpdateMember(member)
  1198  	if nErr != nil {
  1199  		var appErr *model.AppError
  1200  		var nfErr *store.ErrNotFound
  1201  		switch {
  1202  		case errors.As(nErr, &appErr):
  1203  			return nil, appErr
  1204  		case errors.As(nErr, &nfErr):
  1205  			return nil, model.NewAppError("updateChannelMember", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound)
  1206  		default:
  1207  			return nil, model.NewAppError("updateChannelMember", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1208  		}
  1209  	}
  1210  
  1211  	a.InvalidateCacheForUser(member.UserId)
  1212  
  1213  	// Notify the clients that the member notify props changed
  1214  	evt := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", member.UserId, nil)
  1215  	evt.Add("channelMember", member.ToJson())
  1216  	a.Publish(evt)
  1217  
  1218  	return member, nil
  1219  }
  1220  
  1221  func (a *App) DeleteChannel(channel *model.Channel, userID string) *model.AppError {
  1222  	ihc := make(chan store.StoreResult, 1)
  1223  	ohc := make(chan store.StoreResult, 1)
  1224  
  1225  	go func() {
  1226  		webhooks, err := a.Srv().Store.Webhook().GetIncomingByChannel(channel.Id)
  1227  		ihc <- store.StoreResult{Data: webhooks, NErr: err}
  1228  		close(ihc)
  1229  	}()
  1230  
  1231  	go func() {
  1232  		outgoingHooks, err := a.Srv().Store.Webhook().GetOutgoingByChannel(channel.Id, -1, -1)
  1233  		ohc <- store.StoreResult{Data: outgoingHooks, NErr: err}
  1234  		close(ohc)
  1235  	}()
  1236  
  1237  	var user *model.User
  1238  	if userID != "" {
  1239  		var nErr error
  1240  		user, nErr = a.Srv().Store.User().Get(context.Background(), userID)
  1241  		if nErr != nil {
  1242  			var nfErr *store.ErrNotFound
  1243  			switch {
  1244  			case errors.As(nErr, &nfErr):
  1245  				return model.NewAppError("DeleteChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
  1246  			default:
  1247  				return model.NewAppError("DeleteChannel", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1248  			}
  1249  		}
  1250  	}
  1251  
  1252  	ihcresult := <-ihc
  1253  	if ihcresult.NErr != nil {
  1254  		return model.NewAppError("DeleteChannel", "app.webhooks.get_incoming_by_channel.app_error", nil, ihcresult.NErr.Error(), http.StatusInternalServerError)
  1255  	}
  1256  
  1257  	ohcresult := <-ohc
  1258  	if ohcresult.NErr != nil {
  1259  		return model.NewAppError("DeleteChannel", "app.webhooks.get_outgoing_by_channel.app_error", nil, ohcresult.NErr.Error(), http.StatusInternalServerError)
  1260  	}
  1261  
  1262  	incomingHooks := ihcresult.Data.([]*model.IncomingWebhook)
  1263  	outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook)
  1264  
  1265  	if channel.DeleteAt > 0 {
  1266  		err := model.NewAppError("deleteChannel", "api.channel.delete_channel.deleted.app_error", nil, "", http.StatusBadRequest)
  1267  		return err
  1268  	}
  1269  
  1270  	if channel.Name == model.DEFAULT_CHANNEL {
  1271  		err := model.NewAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest)
  1272  		return err
  1273  	}
  1274  
  1275  	if user != nil {
  1276  		T := utils.GetUserTranslations(user.Locale)
  1277  
  1278  		post := &model.Post{
  1279  			ChannelId: channel.Id,
  1280  			Message:   fmt.Sprintf(T("api.channel.delete_channel.archived"), user.Username),
  1281  			Type:      model.POST_CHANNEL_DELETED,
  1282  			UserId:    userID,
  1283  			Props: model.StringInterface{
  1284  				"username": user.Username,
  1285  			},
  1286  		}
  1287  
  1288  		if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1289  			mlog.Warn("Failed to post archive message", mlog.Err(err))
  1290  		}
  1291  	}
  1292  
  1293  	now := model.GetMillis()
  1294  	for _, hook := range incomingHooks {
  1295  		if err := a.Srv().Store.Webhook().DeleteIncoming(hook.Id, now); err != nil {
  1296  			mlog.Warn("Encountered error deleting incoming webhook", mlog.String("hook_id", hook.Id), mlog.Err(err))
  1297  		}
  1298  		a.invalidateCacheForWebhook(hook.Id)
  1299  	}
  1300  
  1301  	for _, hook := range outgoingHooks {
  1302  		if err := a.Srv().Store.Webhook().DeleteOutgoing(hook.Id, now); err != nil {
  1303  			mlog.Warn("Encountered error deleting outgoing webhook", mlog.String("hook_id", hook.Id), mlog.Err(err))
  1304  		}
  1305  	}
  1306  
  1307  	deleteAt := model.GetMillis()
  1308  
  1309  	if err := a.Srv().Store.Channel().Delete(channel.Id, deleteAt); err != nil {
  1310  		return model.NewAppError("DeleteChannel", "app.channel.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
  1311  	}
  1312  	a.invalidateCacheForChannel(channel)
  1313  
  1314  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil)
  1315  	message.Add("channel_id", channel.Id)
  1316  	message.Add("delete_at", deleteAt)
  1317  	a.Publish(message)
  1318  
  1319  	return nil
  1320  }
  1321  
  1322  func (a *App) addUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) {
  1323  	if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE {
  1324  		return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest)
  1325  	}
  1326  
  1327  	channelMember, nErr := a.Srv().Store.Channel().GetMember(channel.Id, user.Id)
  1328  	if nErr != nil {
  1329  		var nfErr *store.ErrNotFound
  1330  		if !errors.As(nErr, &nfErr) {
  1331  			return nil, model.NewAppError("AddUserToChannel", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1332  		}
  1333  	} else {
  1334  		return channelMember, nil
  1335  	}
  1336  
  1337  	if channel.IsGroupConstrained() {
  1338  		nonMembers, err := a.FilterNonGroupChannelMembers([]string{user.Id}, channel)
  1339  		if err != nil {
  1340  			return nil, model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusInternalServerError)
  1341  		}
  1342  		if len(nonMembers) > 0 {
  1343  			return nil, model.NewAppError("addUserToChannel", "api.channel.add_members.user_denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest)
  1344  		}
  1345  	}
  1346  
  1347  	newMember := &model.ChannelMember{
  1348  		ChannelId:   channel.Id,
  1349  		UserId:      user.Id,
  1350  		NotifyProps: model.GetDefaultChannelNotifyProps(),
  1351  		SchemeGuest: user.IsGuest(),
  1352  		SchemeUser:  !user.IsGuest(),
  1353  	}
  1354  
  1355  	if !user.IsGuest() {
  1356  		var userShouldBeAdmin bool
  1357  		userShouldBeAdmin, appErr := a.UserIsInAdminRoleGroup(user.Id, channel.Id, model.GroupSyncableTypeChannel)
  1358  		if appErr != nil {
  1359  			return nil, appErr
  1360  		}
  1361  		newMember.SchemeAdmin = userShouldBeAdmin
  1362  	}
  1363  
  1364  	newMember, nErr = a.Srv().Store.Channel().SaveMember(newMember)
  1365  	if nErr != nil {
  1366  		return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, fmt.Sprintf("failed to add member: user_id: %s, channel_id:%s", user.Id, channel.Id), http.StatusInternalServerError)
  1367  	}
  1368  	a.WaitForChannelMembership(channel.Id, user.Id)
  1369  
  1370  	if nErr := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); nErr != nil {
  1371  		return nil, model.NewAppError("AddUserToChannel", "app.channel_member_history.log_join_event.internal_error", nil, nErr.Error(), http.StatusInternalServerError)
  1372  	}
  1373  
  1374  	a.InvalidateCacheForUser(user.Id)
  1375  	a.invalidateCacheForChannelMembers(channel.Id)
  1376  
  1377  	return newMember, nil
  1378  }
  1379  
  1380  func (a *App) AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) {
  1381  	teamMember, nErr := a.Srv().Store.Team().GetMember(channel.TeamId, user.Id)
  1382  	if nErr != nil {
  1383  		var nfErr *store.ErrNotFound
  1384  		switch {
  1385  		case errors.As(nErr, &nfErr):
  1386  			return nil, model.NewAppError("AddUserToChannel", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1387  		default:
  1388  			return nil, model.NewAppError("AddUserToChannel", "app.team.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1389  		}
  1390  	}
  1391  
  1392  	if teamMember.DeleteAt > 0 {
  1393  		return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "", http.StatusBadRequest)
  1394  	}
  1395  
  1396  	newMember, err := a.addUserToChannel(user, channel)
  1397  	if err != nil {
  1398  		return nil, err
  1399  	}
  1400  
  1401  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil)
  1402  	message.Add("user_id", user.Id)
  1403  	message.Add("team_id", channel.TeamId)
  1404  	a.Publish(message)
  1405  
  1406  	return newMember, nil
  1407  }
  1408  
  1409  func (a *App) AddChannelMember(userID string, channel *model.Channel, userRequestorId string, postRootId string) (*model.ChannelMember, *model.AppError) {
  1410  	if member, err := a.Srv().Store.Channel().GetMember(channel.Id, userID); err != nil {
  1411  		var nfErr *store.ErrNotFound
  1412  		if !errors.As(err, &nfErr) {
  1413  			return nil, model.NewAppError("AddChannelMember", "app.channel.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  1414  		}
  1415  	} else {
  1416  		return member, nil
  1417  	}
  1418  
  1419  	var user *model.User
  1420  	var err *model.AppError
  1421  
  1422  	if user, err = a.GetUser(userID); err != nil {
  1423  		return nil, err
  1424  	}
  1425  
  1426  	var userRequestor *model.User
  1427  	if userRequestorId != "" {
  1428  		if userRequestor, err = a.GetUser(userRequestorId); err != nil {
  1429  			return nil, err
  1430  		}
  1431  	}
  1432  
  1433  	cm, err := a.AddUserToChannel(user, channel)
  1434  	if err != nil {
  1435  		return nil, err
  1436  	}
  1437  
  1438  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
  1439  		a.Srv().Go(func() {
  1440  			pluginContext := a.PluginContext()
  1441  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
  1442  				hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
  1443  				return true
  1444  			}, plugin.UserHasJoinedChannelId)
  1445  		})
  1446  	}
  1447  
  1448  	if userRequestorId == "" || userID == userRequestorId {
  1449  		a.postJoinChannelMessage(user, channel)
  1450  	} else {
  1451  		a.Srv().Go(func() {
  1452  			a.PostAddToChannelMessage(userRequestor, user, channel, postRootId)
  1453  		})
  1454  	}
  1455  
  1456  	return cm, nil
  1457  }
  1458  
  1459  func (a *App) AddDirectChannels(teamID string, user *model.User) *model.AppError {
  1460  	var profiles []*model.User
  1461  	options := &model.UserGetOptions{InTeamId: teamID, Page: 0, PerPage: 100}
  1462  	profiles, err := a.Srv().Store.User().GetProfiles(options)
  1463  	if err != nil {
  1464  		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)
  1465  	}
  1466  
  1467  	var preferences model.Preferences
  1468  
  1469  	for _, profile := range profiles {
  1470  		if profile.Id == user.Id {
  1471  			continue
  1472  		}
  1473  
  1474  		preference := model.Preference{
  1475  			UserId:   user.Id,
  1476  			Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW,
  1477  			Name:     profile.Id,
  1478  			Value:    "true",
  1479  		}
  1480  
  1481  		preferences = append(preferences, preference)
  1482  
  1483  		if len(preferences) >= 10 {
  1484  			break
  1485  		}
  1486  	}
  1487  
  1488  	if err := a.Srv().Store.Preference().Save(&preferences); err != nil {
  1489  		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)
  1490  	}
  1491  
  1492  	return nil
  1493  }
  1494  
  1495  func (a *App) PostUpdateChannelHeaderMessage(userID string, channel *model.Channel, oldChannelHeader, newChannelHeader string) *model.AppError {
  1496  	user, err := a.Srv().Store.User().Get(context.Background(), userID)
  1497  	if err != nil {
  1498  		return model.NewAppError("PostUpdateChannelHeaderMessage", "api.channel.post_update_channel_header_message_and_forget.retrieve_user.error", nil, err.Error(), http.StatusBadRequest)
  1499  	}
  1500  
  1501  	var message string
  1502  	if oldChannelHeader == "" {
  1503  		message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_to"), user.Username, newChannelHeader)
  1504  	} else if newChannelHeader == "" {
  1505  		message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.removed"), user.Username, oldChannelHeader)
  1506  	} else {
  1507  		message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_from"), user.Username, oldChannelHeader, newChannelHeader)
  1508  	}
  1509  
  1510  	post := &model.Post{
  1511  		ChannelId: channel.Id,
  1512  		Message:   message,
  1513  		Type:      model.POST_HEADER_CHANGE,
  1514  		UserId:    userID,
  1515  		Props: model.StringInterface{
  1516  			"username":   user.Username,
  1517  			"old_header": oldChannelHeader,
  1518  			"new_header": newChannelHeader,
  1519  		},
  1520  	}
  1521  
  1522  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1523  		return model.NewAppError("", "api.channel.post_update_channel_header_message_and_forget.post.error", nil, err.Error(), http.StatusInternalServerError)
  1524  	}
  1525  
  1526  	return nil
  1527  }
  1528  
  1529  func (a *App) PostUpdateChannelPurposeMessage(userID string, channel *model.Channel, oldChannelPurpose string, newChannelPurpose string) *model.AppError {
  1530  	user, err := a.Srv().Store.User().Get(context.Background(), userID)
  1531  	if err != nil {
  1532  		return model.NewAppError("PostUpdateChannelPurposeMessage", "app.channel.post_update_channel_purpose_message.retrieve_user.error", nil, err.Error(), http.StatusBadRequest)
  1533  	}
  1534  
  1535  	var message string
  1536  	if oldChannelPurpose == "" {
  1537  		message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_to"), user.Username, newChannelPurpose)
  1538  	} else if newChannelPurpose == "" {
  1539  		message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.removed"), user.Username, oldChannelPurpose)
  1540  	} else {
  1541  		message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_from"), user.Username, oldChannelPurpose, newChannelPurpose)
  1542  	}
  1543  
  1544  	post := &model.Post{
  1545  		ChannelId: channel.Id,
  1546  		Message:   message,
  1547  		Type:      model.POST_PURPOSE_CHANGE,
  1548  		UserId:    userID,
  1549  		Props: model.StringInterface{
  1550  			"username":    user.Username,
  1551  			"old_purpose": oldChannelPurpose,
  1552  			"new_purpose": newChannelPurpose,
  1553  		},
  1554  	}
  1555  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1556  		return model.NewAppError("", "app.channel.post_update_channel_purpose_message.post.error", nil, err.Error(), http.StatusInternalServerError)
  1557  	}
  1558  
  1559  	return nil
  1560  }
  1561  
  1562  func (a *App) PostUpdateChannelDisplayNameMessage(userID string, channel *model.Channel, oldChannelDisplayName, newChannelDisplayName string) *model.AppError {
  1563  	user, err := a.Srv().Store.User().Get(context.Background(), userID)
  1564  	if err != nil {
  1565  		return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.retrieve_user.error", nil, err.Error(), http.StatusBadRequest)
  1566  	}
  1567  
  1568  	message := fmt.Sprintf(utils.T("api.channel.post_update_channel_displayname_message_and_forget.updated_from"), user.Username, oldChannelDisplayName, newChannelDisplayName)
  1569  
  1570  	post := &model.Post{
  1571  		ChannelId: channel.Id,
  1572  		Message:   message,
  1573  		Type:      model.POST_DISPLAYNAME_CHANGE,
  1574  		UserId:    userID,
  1575  		Props: model.StringInterface{
  1576  			"username":        user.Username,
  1577  			"old_displayname": oldChannelDisplayName,
  1578  			"new_displayname": newChannelDisplayName,
  1579  		},
  1580  	}
  1581  
  1582  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1583  		return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.create_post.error", nil, err.Error(), http.StatusInternalServerError)
  1584  	}
  1585  
  1586  	return nil
  1587  }
  1588  
  1589  func (a *App) GetChannel(channelId string) (*model.Channel, *model.AppError) {
  1590  	channel, err := a.Srv().Store.Channel().Get(channelId, true)
  1591  	if err != nil {
  1592  		var nfErr *store.ErrNotFound
  1593  		switch {
  1594  		case errors.As(err, &nfErr):
  1595  			return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1596  		default:
  1597  			return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", nil, err.Error(), http.StatusInternalServerError)
  1598  		}
  1599  	}
  1600  	return channel, nil
  1601  }
  1602  
  1603  func (a *App) GetChannelByName(channelName, teamID string, includeDeleted bool) (*model.Channel, *model.AppError) {
  1604  	var channel *model.Channel
  1605  	var err error
  1606  
  1607  	if includeDeleted {
  1608  		channel, err = a.Srv().Store.Channel().GetByNameIncludeDeleted(teamID, channelName, false)
  1609  	} else {
  1610  		channel, err = a.Srv().Store.Channel().GetByName(teamID, channelName, false)
  1611  	}
  1612  
  1613  	if err != nil {
  1614  		var nfErr *store.ErrNotFound
  1615  		switch {
  1616  		case errors.As(err, &nfErr):
  1617  			return nil, model.NewAppError("GetChannelByName", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1618  		default:
  1619  			return nil, model.NewAppError("GetChannelByName", "app.channel.get_by_name.existing.app_error", nil, err.Error(), http.StatusInternalServerError)
  1620  		}
  1621  	}
  1622  
  1623  	return channel, nil
  1624  }
  1625  
  1626  func (a *App) GetChannelsByNames(channelNames []string, teamID string) ([]*model.Channel, *model.AppError) {
  1627  	channels, err := a.Srv().Store.Channel().GetByNames(teamID, channelNames, true)
  1628  	if err != nil {
  1629  		return nil, model.NewAppError("GetChannelsByNames", "app.channel.get_by_name.existing.app_error", nil, err.Error(), http.StatusInternalServerError)
  1630  	}
  1631  	return channels, nil
  1632  }
  1633  
  1634  func (a *App) GetChannelByNameForTeamName(channelName, teamName string, includeDeleted bool) (*model.Channel, *model.AppError) {
  1635  	var team *model.Team
  1636  
  1637  	team, err := a.Srv().Store.Team().GetByName(teamName)
  1638  	if err != nil {
  1639  		var nfErr *store.ErrNotFound
  1640  		switch {
  1641  		case errors.As(err, &nfErr):
  1642  			return nil, model.NewAppError("GetChannelByNameForTeamName", "app.team.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1643  		default:
  1644  			return nil, model.NewAppError("GetChannelByNameForTeamName", "app.team.get_by_name.app_error", nil, err.Error(), http.StatusNotFound)
  1645  		}
  1646  	}
  1647  
  1648  	var result *model.Channel
  1649  
  1650  	var nErr error
  1651  	if includeDeleted {
  1652  		result, nErr = a.Srv().Store.Channel().GetByNameIncludeDeleted(team.Id, channelName, false)
  1653  	} else {
  1654  		result, nErr = a.Srv().Store.Channel().GetByName(team.Id, channelName, false)
  1655  	}
  1656  
  1657  	if nErr != nil {
  1658  		var nfErr *store.ErrNotFound
  1659  		switch {
  1660  		case errors.As(nErr, &nfErr):
  1661  			return nil, model.NewAppError("GetChannelByNameForTeamName", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1662  		default:
  1663  			return nil, model.NewAppError("GetChannelByNameForTeamName", "app.channel.get_by_name.existing.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1664  		}
  1665  	}
  1666  
  1667  	return result, nil
  1668  }
  1669  
  1670  func (a *App) GetChannelsForUser(teamID string, userID string, includeDeleted bool, lastDeleteAt int) (*model.ChannelList, *model.AppError) {
  1671  	list, err := a.Srv().Store.Channel().GetChannels(teamID, userID, includeDeleted, lastDeleteAt)
  1672  	if err != nil {
  1673  		var nfErr *store.ErrNotFound
  1674  		switch {
  1675  		case errors.As(err, &nfErr):
  1676  			return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1677  		default:
  1678  			return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1679  		}
  1680  	}
  1681  
  1682  	return list, nil
  1683  }
  1684  
  1685  func (a *App) GetAllChannels(page, perPage int, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError) {
  1686  	if opts.ExcludeDefaultChannels {
  1687  		opts.ExcludeChannelNames = a.DefaultChannelNames()
  1688  	}
  1689  	storeOpts := store.ChannelSearchOpts{
  1690  		ExcludeChannelNames:  opts.ExcludeChannelNames,
  1691  		NotAssociatedToGroup: opts.NotAssociatedToGroup,
  1692  		IncludeDeleted:       opts.IncludeDeleted,
  1693  	}
  1694  	channels, err := a.Srv().Store.Channel().GetAllChannels(page*perPage, perPage, storeOpts)
  1695  	if err != nil {
  1696  		return nil, model.NewAppError("GetAllChannels", "app.channel.get_all_channels.app_error", nil, err.Error(), http.StatusInternalServerError)
  1697  	}
  1698  
  1699  	return channels, nil
  1700  }
  1701  
  1702  func (a *App) GetAllChannelsCount(opts model.ChannelSearchOpts) (int64, *model.AppError) {
  1703  	if opts.ExcludeDefaultChannels {
  1704  		opts.ExcludeChannelNames = a.DefaultChannelNames()
  1705  	}
  1706  	storeOpts := store.ChannelSearchOpts{
  1707  		ExcludeChannelNames:  opts.ExcludeChannelNames,
  1708  		NotAssociatedToGroup: opts.NotAssociatedToGroup,
  1709  		IncludeDeleted:       opts.IncludeDeleted,
  1710  	}
  1711  	count, err := a.Srv().Store.Channel().GetAllChannelsCount(storeOpts)
  1712  	if err != nil {
  1713  		return 0, model.NewAppError("GetAllChannelsCount", "app.channel.get_all_channels_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1714  	}
  1715  
  1716  	return count, nil
  1717  }
  1718  
  1719  func (a *App) GetDeletedChannels(teamID string, offset int, limit int, userID string) (*model.ChannelList, *model.AppError) {
  1720  	list, err := a.Srv().Store.Channel().GetDeleted(teamID, offset, limit, userID)
  1721  	if err != nil {
  1722  		var nfErr *store.ErrNotFound
  1723  		switch {
  1724  		case errors.As(err, &nfErr):
  1725  			return nil, model.NewAppError("GetDeletedChannels", "app.channel.get_deleted.missing.app_error", nil, err.Error(), http.StatusNotFound)
  1726  		default:
  1727  			return nil, model.NewAppError("GetDeletedChannels", "app.channel.get_deleted.existing.app_error", nil, err.Error(), http.StatusInternalServerError)
  1728  		}
  1729  	}
  1730  
  1731  	return list, nil
  1732  }
  1733  
  1734  func (a *App) GetChannelsUserNotIn(teamID string, userID string, offset int, limit int) (*model.ChannelList, *model.AppError) {
  1735  	channels, err := a.Srv().Store.Channel().GetMoreChannels(teamID, userID, offset, limit)
  1736  	if err != nil {
  1737  		return nil, model.NewAppError("GetChannelsUserNotIn", "app.channel.get_more_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1738  	}
  1739  	return channels, nil
  1740  }
  1741  
  1742  func (a *App) GetPublicChannelsByIdsForTeam(teamID string, channelIds []string) (*model.ChannelList, *model.AppError) {
  1743  	list, err := a.Srv().Store.Channel().GetPublicChannelsByIdsForTeam(teamID, channelIds)
  1744  	if err != nil {
  1745  		var nfErr *store.ErrNotFound
  1746  		switch {
  1747  		case errors.As(err, &nfErr):
  1748  			return nil, model.NewAppError("GetPublicChannelsByIdsForTeam", "app.channel.get_channels_by_ids.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1749  		default:
  1750  			return nil, model.NewAppError("GetPublicChannelsByIdsForTeam", "app.channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1751  		}
  1752  	}
  1753  
  1754  	return list, nil
  1755  }
  1756  
  1757  func (a *App) GetPublicChannelsForTeam(teamID string, offset int, limit int) (*model.ChannelList, *model.AppError) {
  1758  	list, err := a.Srv().Store.Channel().GetPublicChannelsForTeam(teamID, offset, limit)
  1759  	if err != nil {
  1760  		return nil, model.NewAppError("GetPublicChannelsForTeam", "app.channel.get_public_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1761  	}
  1762  
  1763  	return list, nil
  1764  }
  1765  
  1766  func (a *App) GetPrivateChannelsForTeam(teamID string, offset int, limit int) (*model.ChannelList, *model.AppError) {
  1767  	list, err := a.Srv().Store.Channel().GetPrivateChannelsForTeam(teamID, offset, limit)
  1768  	if err != nil {
  1769  		return nil, model.NewAppError("GetPrivateChannelsForTeam", "app.channel.get_private_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1770  	}
  1771  
  1772  	return list, nil
  1773  }
  1774  
  1775  func (a *App) GetChannelMember(channelId string, userID string) (*model.ChannelMember, *model.AppError) {
  1776  	channelMember, err := a.Srv().Store.Channel().GetMember(channelId, userID)
  1777  	if err != nil {
  1778  		var nfErr *store.ErrNotFound
  1779  		switch {
  1780  		case errors.As(err, &nfErr):
  1781  			return nil, model.NewAppError("GetChannelMember", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound)
  1782  		default:
  1783  			return nil, model.NewAppError("GetChannelMember", "app.channel.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  1784  		}
  1785  	}
  1786  
  1787  	return channelMember, nil
  1788  }
  1789  
  1790  func (a *App) GetChannelMembersPage(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError) {
  1791  	channelMembers, err := a.Srv().Store.Channel().GetMembers(channelId, page*perPage, perPage)
  1792  	if err != nil {
  1793  		return nil, model.NewAppError("GetChannelMembersPage", "app.channel.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1794  	}
  1795  
  1796  	return channelMembers, nil
  1797  }
  1798  
  1799  func (a *App) GetChannelMembersTimezones(channelId string) ([]string, *model.AppError) {
  1800  	membersTimezones, err := a.Srv().Store.Channel().GetChannelMembersTimezones(channelId)
  1801  	if err != nil {
  1802  		return nil, model.NewAppError("GetChannelMembersTimezones", "app.channel.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1803  	}
  1804  
  1805  	var timezones []string
  1806  	for _, membersTimezone := range membersTimezones {
  1807  		if membersTimezone["automaticTimezone"] == "" && membersTimezone["manualTimezone"] == "" {
  1808  			continue
  1809  		}
  1810  		timezones = append(timezones, model.GetPreferredTimezone(membersTimezone))
  1811  	}
  1812  
  1813  	return model.RemoveDuplicateStrings(timezones), nil
  1814  }
  1815  
  1816  func (a *App) GetChannelMembersByIds(channelId string, userIDs []string) (*model.ChannelMembers, *model.AppError) {
  1817  	members, err := a.Srv().Store.Channel().GetMembersByIds(channelId, userIDs)
  1818  	if err != nil {
  1819  		return nil, model.NewAppError("GetChannelMembersByIds", "app.channel.get_members_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
  1820  	}
  1821  
  1822  	return members, nil
  1823  }
  1824  
  1825  func (a *App) GetChannelMembersForUser(teamID string, userID string) (*model.ChannelMembers, *model.AppError) {
  1826  	channelMembers, err := a.Srv().Store.Channel().GetMembersForUser(teamID, userID)
  1827  	if err != nil {
  1828  		return nil, model.NewAppError("GetChannelMembersForUser", "app.channel.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1829  	}
  1830  
  1831  	return channelMembers, nil
  1832  }
  1833  
  1834  func (a *App) GetChannelMembersForUserWithPagination(teamID, userID string, page, perPage int) ([]*model.ChannelMember, *model.AppError) {
  1835  	m, err := a.Srv().Store.Channel().GetMembersForUserWithPagination(teamID, userID, page, perPage)
  1836  	if err != nil {
  1837  		return nil, model.NewAppError("GetChannelMembersForUserWithPagination", "app.channel.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1838  	}
  1839  
  1840  	members := make([]*model.ChannelMember, 0)
  1841  	if m != nil {
  1842  		for _, member := range *m {
  1843  			member := member
  1844  			members = append(members, &member)
  1845  		}
  1846  	}
  1847  	return members, nil
  1848  }
  1849  
  1850  func (a *App) GetChannelMemberCount(channelId string) (int64, *model.AppError) {
  1851  	count, err := a.Srv().Store.Channel().GetMemberCount(channelId, true)
  1852  	if err != nil {
  1853  		return 0, model.NewAppError("GetChannelMemberCount", "app.channel.get_member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1854  	}
  1855  
  1856  	return count, nil
  1857  }
  1858  
  1859  func (a *App) GetChannelGuestCount(channelId string) (int64, *model.AppError) {
  1860  	count, err := a.Srv().Store.Channel().GetGuestCount(channelId, true)
  1861  	if err != nil {
  1862  		return 0, model.NewAppError("SqlChannelStore.GetGuestCount", "app.channel.get_member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1863  	}
  1864  
  1865  	return count, nil
  1866  }
  1867  
  1868  func (a *App) GetChannelPinnedPostCount(channelId string) (int64, *model.AppError) {
  1869  	count, err := a.Srv().Store.Channel().GetPinnedPostCount(channelId, true)
  1870  	if err != nil {
  1871  		return 0, model.NewAppError("GetChannelPinnedPostCount", "app.channel.get_pinnedpost_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1872  	}
  1873  
  1874  	return count, nil
  1875  }
  1876  
  1877  func (a *App) GetChannelCounts(teamID string, userID string) (*model.ChannelCounts, *model.AppError) {
  1878  	counts, err := a.Srv().Store.Channel().GetChannelCounts(teamID, userID)
  1879  	if err != nil {
  1880  		return nil, model.NewAppError("SqlChannelStore.GetChannelCounts", "app.channel.get_channel_counts.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1881  	}
  1882  
  1883  	return counts, nil
  1884  }
  1885  
  1886  func (a *App) GetChannelUnread(channelId, userID string) (*model.ChannelUnread, *model.AppError) {
  1887  	channelUnread, err := a.Srv().Store.Channel().GetChannelUnread(channelId, userID)
  1888  	if err != nil {
  1889  		var nfErr *store.ErrNotFound
  1890  		switch {
  1891  		case errors.As(err, &nfErr):
  1892  			return nil, model.NewAppError("GetChannelUnread", "app.channel.get_unread.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1893  		default:
  1894  			return nil, model.NewAppError("GetChannelUnread", "app.channel.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
  1895  		}
  1896  	}
  1897  
  1898  	if channelUnread.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_MARK_UNREAD_MENTION {
  1899  		channelUnread.MsgCount = 0
  1900  	}
  1901  
  1902  	return channelUnread, nil
  1903  }
  1904  
  1905  func (a *App) JoinChannel(channel *model.Channel, userID string) *model.AppError {
  1906  	userChan := make(chan store.StoreResult, 1)
  1907  	memberChan := make(chan store.StoreResult, 1)
  1908  	go func() {
  1909  		user, err := a.Srv().Store.User().Get(context.Background(), userID)
  1910  		userChan <- store.StoreResult{Data: user, NErr: err}
  1911  		close(userChan)
  1912  	}()
  1913  	go func() {
  1914  		member, err := a.Srv().Store.Channel().GetMember(channel.Id, userID)
  1915  		memberChan <- store.StoreResult{Data: member, NErr: err}
  1916  		close(memberChan)
  1917  	}()
  1918  
  1919  	uresult := <-userChan
  1920  	if uresult.NErr != nil {
  1921  		var nfErr *store.ErrNotFound
  1922  		switch {
  1923  		case errors.As(uresult.NErr, &nfErr):
  1924  			return model.NewAppError("CreateChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
  1925  		default:
  1926  			return model.NewAppError("CreateChannel", "app.user.get.app_error", nil, uresult.NErr.Error(), http.StatusInternalServerError)
  1927  		}
  1928  	}
  1929  
  1930  	mresult := <-memberChan
  1931  	if mresult.NErr == nil && mresult.Data != nil {
  1932  		// user is already in the channel
  1933  		return nil
  1934  	}
  1935  
  1936  	user := uresult.Data.(*model.User)
  1937  
  1938  	if channel.Type != model.CHANNEL_OPEN {
  1939  		return model.NewAppError("JoinChannel", "api.channel.join_channel.permissions.app_error", nil, "", http.StatusBadRequest)
  1940  	}
  1941  
  1942  	cm, err := a.AddUserToChannel(user, channel)
  1943  	if err != nil {
  1944  		return err
  1945  	}
  1946  
  1947  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
  1948  		a.Srv().Go(func() {
  1949  			pluginContext := a.PluginContext()
  1950  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
  1951  				hooks.UserHasJoinedChannel(pluginContext, cm, nil)
  1952  				return true
  1953  			}, plugin.UserHasJoinedChannelId)
  1954  		})
  1955  	}
  1956  
  1957  	if err := a.postJoinChannelMessage(user, channel); err != nil {
  1958  		return err
  1959  	}
  1960  
  1961  	return nil
  1962  }
  1963  
  1964  func (a *App) postJoinChannelMessage(user *model.User, channel *model.Channel) *model.AppError {
  1965  	message := fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username)
  1966  	postType := model.POST_JOIN_CHANNEL
  1967  
  1968  	if user.IsGuest() {
  1969  		message = fmt.Sprintf(utils.T("api.channel.guest_join_channel.post_and_forget"), user.Username)
  1970  		postType = model.POST_GUEST_JOIN_CHANNEL
  1971  	}
  1972  
  1973  	post := &model.Post{
  1974  		ChannelId: channel.Id,
  1975  		Message:   message,
  1976  		Type:      postType,
  1977  		UserId:    user.Id,
  1978  		Props: model.StringInterface{
  1979  			"username": user.Username,
  1980  		},
  1981  	}
  1982  
  1983  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1984  		return model.NewAppError("postJoinChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  1985  	}
  1986  
  1987  	return nil
  1988  }
  1989  
  1990  func (a *App) postJoinTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
  1991  	post := &model.Post{
  1992  		ChannelId: channel.Id,
  1993  		Message:   fmt.Sprintf(utils.T("api.team.join_team.post_and_forget"), user.Username),
  1994  		Type:      model.POST_JOIN_TEAM,
  1995  		UserId:    user.Id,
  1996  		Props: model.StringInterface{
  1997  			"username": user.Username,
  1998  		},
  1999  	}
  2000  
  2001  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2002  		return model.NewAppError("postJoinTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  2003  	}
  2004  
  2005  	return nil
  2006  }
  2007  
  2008  func (a *App) LeaveChannel(channelId string, userID string) *model.AppError {
  2009  	sc := make(chan store.StoreResult, 1)
  2010  	go func() {
  2011  		channel, err := a.Srv().Store.Channel().Get(channelId, true)
  2012  		sc <- store.StoreResult{Data: channel, NErr: err}
  2013  		close(sc)
  2014  	}()
  2015  
  2016  	uc := make(chan store.StoreResult, 1)
  2017  	go func() {
  2018  		user, err := a.Srv().Store.User().Get(context.Background(), userID)
  2019  		uc <- store.StoreResult{Data: user, NErr: err}
  2020  		close(uc)
  2021  	}()
  2022  
  2023  	mcc := make(chan store.StoreResult, 1)
  2024  	go func() {
  2025  		count, err := a.Srv().Store.Channel().GetMemberCount(channelId, false)
  2026  		mcc <- store.StoreResult{Data: count, NErr: err}
  2027  		close(mcc)
  2028  	}()
  2029  
  2030  	cresult := <-sc
  2031  	if cresult.NErr != nil {
  2032  		var nfErr *store.ErrNotFound
  2033  		switch {
  2034  		case errors.As(cresult.NErr, &nfErr):
  2035  			return model.NewAppError("LeaveChannel", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  2036  		default:
  2037  			return model.NewAppError("LeaveChannel", "app.channel.get.find.app_error", nil, cresult.NErr.Error(), http.StatusInternalServerError)
  2038  		}
  2039  	}
  2040  	uresult := <-uc
  2041  	if uresult.NErr != nil {
  2042  		var nfErr *store.ErrNotFound
  2043  		switch {
  2044  		case errors.As(uresult.NErr, &nfErr):
  2045  			return model.NewAppError("LeaveChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
  2046  		default:
  2047  			return model.NewAppError("LeaveChannel", "app.user.get.app_error", nil, uresult.NErr.Error(), http.StatusInternalServerError)
  2048  		}
  2049  	}
  2050  	ccresult := <-mcc
  2051  	if ccresult.NErr != nil {
  2052  		return model.NewAppError("LeaveChannel", "app.channel.get_member_count.app_error", nil, ccresult.NErr.Error(), http.StatusInternalServerError)
  2053  	}
  2054  
  2055  	channel := cresult.Data.(*model.Channel)
  2056  	user := uresult.Data.(*model.User)
  2057  	membersCount := ccresult.Data.(int64)
  2058  
  2059  	if channel.IsGroupOrDirect() {
  2060  		err := model.NewAppError("LeaveChannel", "api.channel.leave.direct.app_error", nil, "", http.StatusBadRequest)
  2061  		return err
  2062  	}
  2063  
  2064  	if channel.Type == model.CHANNEL_PRIVATE && membersCount == 1 {
  2065  		err := model.NewAppError("LeaveChannel", "api.channel.leave.last_member.app_error", nil, "userId="+user.Id, http.StatusBadRequest)
  2066  		return err
  2067  	}
  2068  
  2069  	if err := a.removeUserFromChannel(userID, userID, channel); err != nil {
  2070  		return err
  2071  	}
  2072  
  2073  	if channel.Name == model.DEFAULT_CHANNEL && !*a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
  2074  		return nil
  2075  	}
  2076  
  2077  	a.Srv().Go(func() {
  2078  		a.postLeaveChannelMessage(user, channel)
  2079  	})
  2080  
  2081  	return nil
  2082  }
  2083  
  2084  func (a *App) postLeaveChannelMessage(user *model.User, channel *model.Channel) *model.AppError {
  2085  	post := &model.Post{
  2086  		ChannelId: channel.Id,
  2087  		// Message here embeds `@username`, not just `username`, to ensure that mentions
  2088  		// treat this as a username mention even though the user has now left the channel.
  2089  		// The client renders its own system message, ignoring this value altogether.
  2090  		Message: fmt.Sprintf(utils.T("api.channel.leave.left"), fmt.Sprintf("@%s", user.Username)),
  2091  		Type:    model.POST_LEAVE_CHANNEL,
  2092  		UserId:  user.Id,
  2093  		Props: model.StringInterface{
  2094  			"username": user.Username,
  2095  		},
  2096  	}
  2097  
  2098  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2099  		return model.NewAppError("postLeaveChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  2100  	}
  2101  
  2102  	return nil
  2103  }
  2104  
  2105  func (a *App) PostAddToChannelMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError {
  2106  	message := fmt.Sprintf(utils.T("api.channel.add_member.added"), addedUser.Username, user.Username)
  2107  	postType := model.POST_ADD_TO_CHANNEL
  2108  
  2109  	if addedUser.IsGuest() {
  2110  		message = fmt.Sprintf(utils.T("api.channel.add_guest.added"), addedUser.Username, user.Username)
  2111  		postType = model.POST_ADD_GUEST_TO_CHANNEL
  2112  	}
  2113  
  2114  	post := &model.Post{
  2115  		ChannelId: channel.Id,
  2116  		Message:   message,
  2117  		Type:      postType,
  2118  		UserId:    user.Id,
  2119  		RootId:    postRootId,
  2120  		Props: model.StringInterface{
  2121  			"userId":                       user.Id,
  2122  			"username":                     user.Username,
  2123  			model.POST_PROPS_ADDED_USER_ID: addedUser.Id,
  2124  			"addedUsername":                addedUser.Username,
  2125  		},
  2126  	}
  2127  
  2128  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2129  		return model.NewAppError("postAddToChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  2130  	}
  2131  
  2132  	return nil
  2133  }
  2134  
  2135  func (a *App) postAddToTeamMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError {
  2136  	post := &model.Post{
  2137  		ChannelId: channel.Id,
  2138  		Message:   fmt.Sprintf(utils.T("api.team.add_user_to_team.added"), addedUser.Username, user.Username),
  2139  		Type:      model.POST_ADD_TO_TEAM,
  2140  		UserId:    user.Id,
  2141  		RootId:    postRootId,
  2142  		Props: model.StringInterface{
  2143  			"userId":                       user.Id,
  2144  			"username":                     user.Username,
  2145  			model.POST_PROPS_ADDED_USER_ID: addedUser.Id,
  2146  			"addedUsername":                addedUser.Username,
  2147  		},
  2148  	}
  2149  
  2150  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2151  		return model.NewAppError("postAddToTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  2152  	}
  2153  
  2154  	return nil
  2155  }
  2156  
  2157  func (a *App) postRemoveFromChannelMessage(removerUserId string, removedUser *model.User, channel *model.Channel) *model.AppError {
  2158  	post := &model.Post{
  2159  		ChannelId: channel.Id,
  2160  		// Message here embeds `@username`, not just `username`, to ensure that mentions
  2161  		// treat this as a username mention even though the user has now left the channel.
  2162  		// The client renders its own system message, ignoring this value altogether.
  2163  		Message: fmt.Sprintf(utils.T("api.channel.remove_member.removed"), fmt.Sprintf("@%s", removedUser.Username)),
  2164  		Type:    model.POST_REMOVE_FROM_CHANNEL,
  2165  		UserId:  removerUserId,
  2166  		Props: model.StringInterface{
  2167  			"removedUserId":   removedUser.Id,
  2168  			"removedUsername": removedUser.Username,
  2169  		},
  2170  	}
  2171  
  2172  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2173  		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  2174  	}
  2175  
  2176  	return nil
  2177  }
  2178  
  2179  func (a *App) removeUserFromChannel(userIDToRemove string, removerUserId string, channel *model.Channel) *model.AppError {
  2180  	user, nErr := a.Srv().Store.User().Get(context.Background(), userIDToRemove)
  2181  	if nErr != nil {
  2182  		var nfErr *store.ErrNotFound
  2183  		switch {
  2184  		case errors.As(nErr, &nfErr):
  2185  			return model.NewAppError("removeUserFromChannel", MissingAccountError, nil, nfErr.Error(), http.StatusNotFound)
  2186  		default:
  2187  			return model.NewAppError("removeUserFromChannel", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2188  		}
  2189  	}
  2190  	isGuest := user.IsGuest()
  2191  
  2192  	if channel.Name == model.DEFAULT_CHANNEL {
  2193  		if !isGuest {
  2194  			return model.NewAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest)
  2195  		}
  2196  	}
  2197  
  2198  	if channel.IsGroupConstrained() && userIDToRemove != removerUserId && !user.IsBot {
  2199  		nonMembers, err := a.FilterNonGroupChannelMembers([]string{userIDToRemove}, channel)
  2200  		if err != nil {
  2201  			return model.NewAppError("removeUserFromChannel", "api.channel.remove_user_from_channel.app_error", nil, "", http.StatusInternalServerError)
  2202  		}
  2203  		if len(nonMembers) == 0 {
  2204  			return model.NewAppError("removeUserFromChannel", "api.channel.remove_members.denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest)
  2205  		}
  2206  	}
  2207  
  2208  	cm, err := a.GetChannelMember(channel.Id, userIDToRemove)
  2209  	if err != nil {
  2210  		return err
  2211  	}
  2212  
  2213  	if err := a.Srv().Store.Channel().RemoveMember(channel.Id, userIDToRemove); err != nil {
  2214  		return model.NewAppError("removeUserFromChannel", "app.channel.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  2215  	}
  2216  	if err := a.Srv().Store.ChannelMemberHistory().LogLeaveEvent(userIDToRemove, channel.Id, model.GetMillis()); err != nil {
  2217  		return model.NewAppError("removeUserFromChannel", "app.channel_member_history.log_leave_event.internal_error", nil, err.Error(), http.StatusInternalServerError)
  2218  	}
  2219  
  2220  	if isGuest {
  2221  		currentMembers, err := a.GetChannelMembersForUser(channel.TeamId, userIDToRemove)
  2222  		if err != nil {
  2223  			return err
  2224  		}
  2225  		if len(*currentMembers) == 0 {
  2226  			teamMember, err := a.GetTeamMember(channel.TeamId, userIDToRemove)
  2227  			if err != nil {
  2228  				return model.NewAppError("removeUserFromChannel", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
  2229  			}
  2230  
  2231  			if err = a.RemoveTeamMemberFromTeam(teamMember, removerUserId); err != nil {
  2232  				return err
  2233  			}
  2234  		}
  2235  	}
  2236  
  2237  	a.InvalidateCacheForUser(userIDToRemove)
  2238  	a.invalidateCacheForChannelMembers(channel.Id)
  2239  
  2240  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
  2241  		var actorUser *model.User
  2242  		if removerUserId != "" {
  2243  			actorUser, _ = a.GetUser(removerUserId)
  2244  		}
  2245  
  2246  		a.Srv().Go(func() {
  2247  			pluginContext := a.PluginContext()
  2248  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
  2249  				hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
  2250  				return true
  2251  			}, plugin.UserHasLeftChannelId)
  2252  		})
  2253  	}
  2254  
  2255  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil)
  2256  	message.Add("user_id", userIDToRemove)
  2257  	message.Add("remover_id", removerUserId)
  2258  	a.Publish(message)
  2259  
  2260  	// because the removed user no longer belongs to the channel we need to send a separate websocket event
  2261  	userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIDToRemove, nil)
  2262  	userMsg.Add("channel_id", channel.Id)
  2263  	userMsg.Add("remover_id", removerUserId)
  2264  	a.Publish(userMsg)
  2265  
  2266  	return nil
  2267  }
  2268  
  2269  func (a *App) RemoveUserFromChannel(userIDToRemove string, removerUserId string, channel *model.Channel) *model.AppError {
  2270  	var err *model.AppError
  2271  
  2272  	if err = a.removeUserFromChannel(userIDToRemove, removerUserId, channel); err != nil {
  2273  		return err
  2274  	}
  2275  
  2276  	var user *model.User
  2277  	if user, err = a.GetUser(userIDToRemove); err != nil {
  2278  		return err
  2279  	}
  2280  
  2281  	if userIDToRemove == removerUserId {
  2282  		if err := a.postLeaveChannelMessage(user, channel); err != nil {
  2283  			return err
  2284  		}
  2285  	} else {
  2286  		a.Srv().Go(func() {
  2287  			a.postRemoveFromChannelMessage(removerUserId, user, channel)
  2288  		})
  2289  	}
  2290  
  2291  	return nil
  2292  }
  2293  
  2294  func (a *App) GetNumberOfChannelsOnTeam(teamID string) (int, *model.AppError) {
  2295  	// Get total number of channels on current team
  2296  	list, err := a.Srv().Store.Channel().GetTeamChannels(teamID)
  2297  	if err != nil {
  2298  		var nfErr *store.ErrNotFound
  2299  		switch {
  2300  		case errors.As(err, &nfErr):
  2301  			return 0, model.NewAppError("GetNumberOfChannelsOnTeam", "app.channel.get_channels.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound)
  2302  		default:
  2303  			return 0, model.NewAppError("GetNumberOfChannelsOnTeam", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  2304  		}
  2305  	}
  2306  	return len(*list), nil
  2307  }
  2308  
  2309  func (a *App) SetActiveChannel(userID string, channelId string) *model.AppError {
  2310  	status, err := a.GetStatus(userID)
  2311  
  2312  	oldStatus := model.STATUS_OFFLINE
  2313  
  2314  	if err != nil {
  2315  		status = &model.Status{UserId: userID, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: channelId}
  2316  	} else {
  2317  		oldStatus = status.Status
  2318  		status.ActiveChannel = channelId
  2319  		if !status.Manual && channelId != "" {
  2320  			status.Status = model.STATUS_ONLINE
  2321  		}
  2322  		status.LastActivityAt = model.GetMillis()
  2323  	}
  2324  
  2325  	a.AddStatusCache(status)
  2326  
  2327  	if status.Status != oldStatus {
  2328  		a.BroadcastStatus(status)
  2329  	}
  2330  
  2331  	return nil
  2332  }
  2333  
  2334  func (a *App) UpdateChannelLastViewedAt(channelIds []string, userID string) *model.AppError {
  2335  	if _, err := a.Srv().Store.Channel().UpdateLastViewedAt(channelIds, userID, *a.Config().ServiceSettings.ThreadAutoFollow); err != nil {
  2336  		var invErr *store.ErrInvalidInput
  2337  		switch {
  2338  		case errors.As(err, &invErr):
  2339  			return model.NewAppError("UpdateChannelLastViewedAt", "app.channel.update_last_viewed_at.app_error", nil, invErr.Error(), http.StatusBadRequest)
  2340  		default:
  2341  			return model.NewAppError("UpdateChannelLastViewedAt", "app.channel.update_last_viewed_at.app_error", nil, err.Error(), http.StatusInternalServerError)
  2342  		}
  2343  	}
  2344  
  2345  	if *a.Config().ServiceSettings.EnableChannelViewedMessages {
  2346  		for _, channelId := range channelIds {
  2347  			message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userID, nil)
  2348  			message.Add("channel_id", channelId)
  2349  			a.Publish(message)
  2350  		}
  2351  	}
  2352  
  2353  	return nil
  2354  }
  2355  
  2356  // MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one.
  2357  func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string) (*model.ChannelUnreadAt, *model.AppError) {
  2358  	post, err := a.GetSinglePost(postID)
  2359  	if err != nil {
  2360  		return nil, err
  2361  	}
  2362  
  2363  	user, err := a.GetUser(userID)
  2364  	if err != nil {
  2365  		return nil, err
  2366  	}
  2367  
  2368  	unreadMentions, err := a.countMentionsFromPost(user, post)
  2369  	if err != nil {
  2370  		return nil, err
  2371  	}
  2372  
  2373  	if *a.Config().ServiceSettings.ThreadAutoFollow && post.RootId != "" {
  2374  		threadMembership, _ := a.Srv().Store.Thread().GetMembershipForUser(user.Id, post.RootId)
  2375  		if threadMembership != nil {
  2376  			channel, nErr := a.Srv().Store.Channel().Get(post.ChannelId, true)
  2377  			if nErr != nil {
  2378  				return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2379  			}
  2380  			threadMembership.UnreadMentions, err = a.countThreadMentions(user, post, channel.TeamId, post.UpdateAt-1)
  2381  			if err != nil {
  2382  				return nil, err
  2383  			}
  2384  			_, nErr = a.Srv().Store.Thread().UpdateMembership(threadMembership)
  2385  			if nErr != nil {
  2386  				return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2387  			}
  2388  		}
  2389  	}
  2390  
  2391  	channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, *a.Config().ServiceSettings.ThreadAutoFollow)
  2392  	if nErr != nil {
  2393  		return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2394  	}
  2395  
  2396  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_UNREAD, channelUnread.TeamId, channelUnread.ChannelId, channelUnread.UserId, nil)
  2397  	message.Add("msg_count", channelUnread.MsgCount)
  2398  	message.Add("mention_count", channelUnread.MentionCount)
  2399  	message.Add("last_viewed_at", channelUnread.LastViewedAt)
  2400  	message.Add("post_id", postID)
  2401  	a.Publish(message)
  2402  
  2403  	a.UpdateMobileAppBadge(userID)
  2404  
  2405  	return channelUnread, nil
  2406  }
  2407  
  2408  func (a *App) AutocompleteChannels(teamID string, term string) (*model.ChannelList, *model.AppError) {
  2409  	includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels
  2410  	term = strings.TrimSpace(term)
  2411  
  2412  	channelList, err := a.Srv().Store.Channel().AutocompleteInTeam(teamID, term, includeDeleted)
  2413  	if err != nil {
  2414  		return nil, model.NewAppError("AutocompleteChannels", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2415  	}
  2416  
  2417  	return channelList, nil
  2418  }
  2419  
  2420  func (a *App) AutocompleteChannelsForSearch(teamID string, userID string, term string) (*model.ChannelList, *model.AppError) {
  2421  	includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels
  2422  
  2423  	term = strings.TrimSpace(term)
  2424  
  2425  	channelList, err := a.Srv().Store.Channel().AutocompleteInTeamForSearch(teamID, userID, term, includeDeleted)
  2426  	if err != nil {
  2427  		return nil, model.NewAppError("AutocompleteChannelsForSearch", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2428  	}
  2429  
  2430  	return channelList, nil
  2431  }
  2432  
  2433  // SearchAllChannels returns a list of channels, the total count of the results of the search (if the paginate search option is true), and an error.
  2434  func (a *App) SearchAllChannels(term string, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, int64, *model.AppError) {
  2435  	if opts.ExcludeDefaultChannels {
  2436  		opts.ExcludeChannelNames = a.DefaultChannelNames()
  2437  	}
  2438  	storeOpts := store.ChannelSearchOpts{
  2439  		ExcludeChannelNames:     opts.ExcludeChannelNames,
  2440  		NotAssociatedToGroup:    opts.NotAssociatedToGroup,
  2441  		IncludeDeleted:          opts.IncludeDeleted,
  2442  		Deleted:                 opts.Deleted,
  2443  		TeamIds:                 opts.TeamIds,
  2444  		GroupConstrained:        opts.GroupConstrained,
  2445  		ExcludeGroupConstrained: opts.ExcludeGroupConstrained,
  2446  		Public:                  opts.Public,
  2447  		Private:                 opts.Private,
  2448  		Page:                    opts.Page,
  2449  		PerPage:                 opts.PerPage,
  2450  	}
  2451  
  2452  	term = strings.TrimSpace(term)
  2453  
  2454  	channelList, totalCount, err := a.Srv().Store.Channel().SearchAllChannels(term, storeOpts)
  2455  	if err != nil {
  2456  		return nil, 0, model.NewAppError("SearchAllChannels", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2457  	}
  2458  
  2459  	return channelList, totalCount, nil
  2460  }
  2461  
  2462  func (a *App) SearchChannels(teamID string, term string) (*model.ChannelList, *model.AppError) {
  2463  	includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels
  2464  
  2465  	term = strings.TrimSpace(term)
  2466  
  2467  	channelList, err := a.Srv().Store.Channel().SearchInTeam(teamID, term, includeDeleted)
  2468  	if err != nil {
  2469  		return nil, model.NewAppError("SearchChannels", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2470  	}
  2471  
  2472  	return channelList, nil
  2473  }
  2474  
  2475  func (a *App) SearchArchivedChannels(teamID string, term string, userID string) (*model.ChannelList, *model.AppError) {
  2476  	term = strings.TrimSpace(term)
  2477  
  2478  	channelList, err := a.Srv().Store.Channel().SearchArchivedInTeam(teamID, term, userID)
  2479  	if err != nil {
  2480  		return nil, model.NewAppError("SearchArchivedChannels", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2481  	}
  2482  
  2483  	return channelList, nil
  2484  }
  2485  
  2486  func (a *App) SearchChannelsForUser(userID, teamID, term string) (*model.ChannelList, *model.AppError) {
  2487  	includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels
  2488  
  2489  	term = strings.TrimSpace(term)
  2490  
  2491  	channelList, err := a.Srv().Store.Channel().SearchForUserInTeam(userID, teamID, term, includeDeleted)
  2492  	if err != nil {
  2493  		return nil, model.NewAppError("SearchChannelsForUser", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2494  	}
  2495  
  2496  	return channelList, nil
  2497  }
  2498  
  2499  func (a *App) SearchGroupChannels(userID, term string) (*model.ChannelList, *model.AppError) {
  2500  	if term == "" {
  2501  		return &model.ChannelList{}, nil
  2502  	}
  2503  
  2504  	channelList, err := a.Srv().Store.Channel().SearchGroupChannels(userID, term)
  2505  	if err != nil {
  2506  		return nil, model.NewAppError("SearchGroupChannels", "app.channel.search_group_channels.app_error", nil, err.Error(), http.StatusInternalServerError)
  2507  	}
  2508  	return channelList, nil
  2509  }
  2510  
  2511  func (a *App) SearchChannelsUserNotIn(teamID string, userID string, term string) (*model.ChannelList, *model.AppError) {
  2512  	term = strings.TrimSpace(term)
  2513  	channelList, err := a.Srv().Store.Channel().SearchMore(userID, teamID, term)
  2514  	if err != nil {
  2515  		return nil, model.NewAppError("SearchChannelsUserNotIn", "app.channel.search.app_error", nil, err.Error(), http.StatusInternalServerError)
  2516  	}
  2517  
  2518  	return channelList, nil
  2519  }
  2520  
  2521  func (a *App) MarkChannelsAsViewed(channelIds []string, userID string, currentSessionId string) (map[string]int64, *model.AppError) {
  2522  	// I start looking for channels with notifications before I mark it as read, to clear the push notifications if needed
  2523  	channelsToClearPushNotifications := []string{}
  2524  	if *a.Config().EmailSettings.SendPushNotifications {
  2525  		for _, channelId := range channelIds {
  2526  			channel, errCh := a.Srv().Store.Channel().Get(channelId, true)
  2527  			if errCh != nil {
  2528  				mlog.Warn("Failed to get channel", mlog.Err(errCh))
  2529  				continue
  2530  			}
  2531  
  2532  			member, err := a.Srv().Store.Channel().GetMember(channelId, userID)
  2533  			if err != nil {
  2534  				mlog.Warn("Failed to get membership", mlog.Err(err))
  2535  				continue
  2536  			}
  2537  
  2538  			notify := member.NotifyProps[model.PUSH_NOTIFY_PROP]
  2539  			if notify == model.CHANNEL_NOTIFY_DEFAULT {
  2540  				user, err := a.GetUser(userID)
  2541  				if err != nil {
  2542  					mlog.Warn("Failed to get user", mlog.String("user_id", userID), mlog.Err(err))
  2543  					continue
  2544  				}
  2545  				notify = user.NotifyProps[model.PUSH_NOTIFY_PROP]
  2546  			}
  2547  			if notify == model.USER_NOTIFY_ALL {
  2548  				if count, err := a.Srv().Store.User().GetAnyUnreadPostCountForChannel(userID, channelId); err == nil {
  2549  					if count > 0 {
  2550  						channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId)
  2551  					}
  2552  				}
  2553  			} else if notify == model.USER_NOTIFY_MENTION || channel.Type == model.CHANNEL_DIRECT {
  2554  				if count, err := a.Srv().Store.User().GetUnreadCountForChannel(userID, channelId); err == nil {
  2555  					if count > 0 {
  2556  						channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId)
  2557  					}
  2558  				}
  2559  			}
  2560  		}
  2561  	}
  2562  	times, err := a.Srv().Store.Channel().UpdateLastViewedAt(channelIds, userID, *a.Config().ServiceSettings.ThreadAutoFollow)
  2563  	if err != nil {
  2564  		var invErr *store.ErrInvalidInput
  2565  		switch {
  2566  		case errors.As(err, &invErr):
  2567  			return nil, model.NewAppError("MarkChannelsAsViewed", "app.channel.update_last_viewed_at.app_error", nil, invErr.Error(), http.StatusBadRequest)
  2568  		default:
  2569  			return nil, model.NewAppError("MarkChannelsAsViewed", "app.channel.update_last_viewed_at.app_error", nil, err.Error(), http.StatusInternalServerError)
  2570  		}
  2571  	}
  2572  
  2573  	if *a.Config().ServiceSettings.EnableChannelViewedMessages {
  2574  		for _, channelId := range channelIds {
  2575  			message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userID, nil)
  2576  			message.Add("channel_id", channelId)
  2577  			a.Publish(message)
  2578  		}
  2579  	}
  2580  	for _, channelId := range channelsToClearPushNotifications {
  2581  		a.clearPushNotification(currentSessionId, userID, channelId)
  2582  	}
  2583  	return times, nil
  2584  }
  2585  
  2586  func (a *App) ViewChannel(view *model.ChannelView, userID string, currentSessionId string) (map[string]int64, *model.AppError) {
  2587  	if err := a.SetActiveChannel(userID, view.ChannelId); err != nil {
  2588  		return nil, err
  2589  	}
  2590  
  2591  	channelIds := []string{}
  2592  
  2593  	if view.ChannelId != "" {
  2594  		channelIds = append(channelIds, view.ChannelId)
  2595  	}
  2596  
  2597  	if view.PrevChannelId != "" {
  2598  		channelIds = append(channelIds, view.PrevChannelId)
  2599  	}
  2600  
  2601  	if len(channelIds) == 0 {
  2602  		return map[string]int64{}, nil
  2603  	}
  2604  
  2605  	return a.MarkChannelsAsViewed(channelIds, userID, currentSessionId)
  2606  }
  2607  
  2608  func (a *App) PermanentDeleteChannel(channel *model.Channel) *model.AppError {
  2609  	if err := a.Srv().Store.Post().PermanentDeleteByChannel(channel.Id); err != nil {
  2610  		return model.NewAppError("PermanentDeleteChannel", "app.post.permanent_delete_by_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
  2611  	}
  2612  
  2613  	if err := a.Srv().Store.Channel().PermanentDeleteMembersByChannel(channel.Id); err != nil {
  2614  		return model.NewAppError("PermanentDeleteChannel", "app.channel.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  2615  	}
  2616  
  2617  	if err := a.Srv().Store.Webhook().PermanentDeleteIncomingByChannel(channel.Id); err != nil {
  2618  		return model.NewAppError("PermanentDeleteChannel", "app.webhooks.permanent_delete_incoming_by_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
  2619  	}
  2620  
  2621  	if err := a.Srv().Store.Webhook().PermanentDeleteOutgoingByChannel(channel.Id); err != nil {
  2622  		return model.NewAppError("PermanentDeleteChannel", "app.webhooks.permanent_delete_outgoing_by_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
  2623  	}
  2624  
  2625  	deleteAt := model.GetMillis()
  2626  
  2627  	if nErr := a.Srv().Store.Channel().PermanentDelete(channel.Id); nErr != nil {
  2628  		return model.NewAppError("PermanentDeleteChannel", "app.channel.permanent_delete.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2629  	}
  2630  
  2631  	a.invalidateCacheForChannel(channel)
  2632  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil)
  2633  	message.Add("channel_id", channel.Id)
  2634  	message.Add("delete_at", deleteAt)
  2635  	a.Publish(message)
  2636  
  2637  	return nil
  2638  }
  2639  
  2640  func (a *App) RemoveAllDeactivatedMembersFromChannel(channel *model.Channel) *model.AppError {
  2641  	err := a.Srv().Store.Channel().RemoveAllDeactivatedMembers(channel.Id)
  2642  	if err != nil {
  2643  		return model.NewAppError("RemoveAllDeactivatedMembersFromChannel", "app.channel.remove_all_deactivated_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  2644  	}
  2645  
  2646  	return nil
  2647  }
  2648  
  2649  // MoveChannel method is prone to data races if someone joins to channel during the move process. However this
  2650  // function is only exposed to sysadmins and the possibility of this edge case is relatively small.
  2651  func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.User) *model.AppError {
  2652  	// Check that all channel members are in the destination team.
  2653  	channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000)
  2654  	if err != nil {
  2655  		return err
  2656  	}
  2657  
  2658  	channelMemberIds := []string{}
  2659  	for _, channelMember := range *channelMembers {
  2660  		channelMemberIds = append(channelMemberIds, channelMember.UserId)
  2661  	}
  2662  
  2663  	if len(channelMemberIds) > 0 {
  2664  		teamMembers, err2 := a.GetTeamMembersByIds(team.Id, channelMemberIds, nil)
  2665  		if err2 != nil {
  2666  			return err2
  2667  		}
  2668  
  2669  		if len(teamMembers) != len(*channelMembers) {
  2670  			teamMembersMap := make(map[string]*model.TeamMember, len(teamMembers))
  2671  			for _, teamMember := range teamMembers {
  2672  				teamMembersMap[teamMember.UserId] = teamMember
  2673  			}
  2674  			for _, channelMember := range *channelMembers {
  2675  				if _, ok := teamMembersMap[channelMember.UserId]; !ok {
  2676  					mlog.Warn("Not member of the target team", mlog.String("userId", channelMember.UserId))
  2677  				}
  2678  			}
  2679  			return model.NewAppError("MoveChannel", "app.channel.move_channel.members_do_not_match.error", nil, "", http.StatusInternalServerError)
  2680  		}
  2681  	}
  2682  
  2683  	// keep instance of the previous team
  2684  	previousTeam, nErr := a.Srv().Store.Team().Get(channel.TeamId)
  2685  	if nErr != nil {
  2686  		var nfErr *store.ErrNotFound
  2687  		switch {
  2688  		case errors.As(nErr, &nfErr):
  2689  			return model.NewAppError("MoveChannel", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
  2690  		default:
  2691  			return model.NewAppError("MoveChannel", "app.team.get.finding.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2692  		}
  2693  	}
  2694  
  2695  	if nErr := a.Srv().Store.Channel().UpdateSidebarChannelCategoryOnMove(channel, team.Id); nErr != nil {
  2696  		return model.NewAppError("MoveChannel", "app.channel.sidebar_categories.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2697  	}
  2698  
  2699  	channel.TeamId = team.Id
  2700  	if _, err := a.Srv().Store.Channel().Update(channel); err != nil {
  2701  		var appErr *model.AppError
  2702  		var invErr *store.ErrInvalidInput
  2703  		switch {
  2704  		case errors.As(err, &invErr):
  2705  			return model.NewAppError("MoveChannel", "app.channel.update.bad_id", nil, invErr.Error(), http.StatusBadRequest)
  2706  		case errors.As(err, &appErr):
  2707  			return appErr
  2708  		default:
  2709  			return model.NewAppError("MoveChannel", "app.channel.update_channel.internal_error", nil, err.Error(), http.StatusInternalServerError)
  2710  		}
  2711  	}
  2712  
  2713  	if incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(previousTeam.Id, 0, 10000000); err != nil {
  2714  		mlog.Warn("Failed to get incoming webhooks", mlog.Err(err))
  2715  	} else {
  2716  		for _, webhook := range incomingWebhooks {
  2717  			if webhook.ChannelId == channel.Id {
  2718  				webhook.TeamId = team.Id
  2719  				if _, err := a.Srv().Store.Webhook().UpdateIncoming(webhook); err != nil {
  2720  					mlog.Warn("Failed to move incoming webhook to new team", mlog.String("webhook id", webhook.Id))
  2721  				}
  2722  			}
  2723  		}
  2724  	}
  2725  
  2726  	if outgoingWebhooks, err := a.GetOutgoingWebhooksForTeamPage(previousTeam.Id, 0, 10000000); err != nil {
  2727  		mlog.Warn("Failed to get outgoing webhooks", mlog.Err(err))
  2728  	} else {
  2729  		for _, webhook := range outgoingWebhooks {
  2730  			if webhook.ChannelId == channel.Id {
  2731  				webhook.TeamId = team.Id
  2732  				if _, err := a.Srv().Store.Webhook().UpdateOutgoing(webhook); err != nil {
  2733  					mlog.Warn("Failed to move outgoing webhook to new team.", mlog.String("webhook id", webhook.Id))
  2734  				}
  2735  			}
  2736  		}
  2737  	}
  2738  
  2739  	if err := a.RemoveUsersFromChannelNotMemberOfTeam(user, channel, team); err != nil {
  2740  		mlog.Warn("error while removing non-team member users", mlog.Err(err))
  2741  	}
  2742  
  2743  	if user != nil {
  2744  		if err := a.postChannelMoveMessage(user, channel, previousTeam); err != nil {
  2745  			mlog.Warn("error while posting move channel message", mlog.Err(err))
  2746  		}
  2747  	}
  2748  
  2749  	return nil
  2750  }
  2751  
  2752  func (a *App) postChannelMoveMessage(user *model.User, channel *model.Channel, previousTeam *model.Team) *model.AppError {
  2753  
  2754  	post := &model.Post{
  2755  		ChannelId: channel.Id,
  2756  		Message:   fmt.Sprintf(utils.T("api.team.move_channel.success"), previousTeam.Name),
  2757  		Type:      model.POST_MOVE_CHANNEL,
  2758  		UserId:    user.Id,
  2759  		Props: model.StringInterface{
  2760  			"username": user.Username,
  2761  		},
  2762  	}
  2763  
  2764  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  2765  		return model.NewAppError("postChannelMoveMessage", "api.team.move_channel.post.error", nil, err.Error(), http.StatusInternalServerError)
  2766  	}
  2767  
  2768  	return nil
  2769  }
  2770  
  2771  func (a *App) RemoveUsersFromChannelNotMemberOfTeam(remover *model.User, channel *model.Channel, team *model.Team) *model.AppError {
  2772  	channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000)
  2773  	if err != nil {
  2774  		return err
  2775  	}
  2776  
  2777  	channelMemberIds := []string{}
  2778  	channelMemberMap := make(map[string]struct{})
  2779  	for _, channelMember := range *channelMembers {
  2780  		channelMemberMap[channelMember.UserId] = struct{}{}
  2781  		channelMemberIds = append(channelMemberIds, channelMember.UserId)
  2782  	}
  2783  
  2784  	if len(channelMemberIds) > 0 {
  2785  		teamMembers, err := a.GetTeamMembersByIds(team.Id, channelMemberIds, nil)
  2786  		if err != nil {
  2787  			return err
  2788  		}
  2789  
  2790  		if len(teamMembers) != len(*channelMembers) {
  2791  			for _, teamMember := range teamMembers {
  2792  				delete(channelMemberMap, teamMember.UserId)
  2793  			}
  2794  
  2795  			var removerId string
  2796  			if remover != nil {
  2797  				removerId = remover.Id
  2798  			}
  2799  			for userID := range channelMemberMap {
  2800  				if err := a.removeUserFromChannel(userID, removerId, channel); err != nil {
  2801  					return err
  2802  				}
  2803  			}
  2804  		}
  2805  	}
  2806  
  2807  	return nil
  2808  }
  2809  
  2810  func (a *App) GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) {
  2811  	posts, err := a.Srv().Store.Channel().GetPinnedPosts(channelId)
  2812  	if err != nil {
  2813  		return nil, model.NewAppError("GetPinnedPosts", "app.channel.pinned_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
  2814  	}
  2815  
  2816  	return posts, nil
  2817  }
  2818  
  2819  func (a *App) ToggleMuteChannel(channelId, userID string) (*model.ChannelMember, *model.AppError) {
  2820  	member, nErr := a.Srv().Store.Channel().GetMember(channelId, userID)
  2821  	if nErr != nil {
  2822  		var appErr *model.AppError
  2823  		var nfErr *store.ErrNotFound
  2824  		switch {
  2825  		case errors.As(nErr, &appErr):
  2826  			return nil, appErr
  2827  		case errors.As(nErr, &nfErr):
  2828  			return nil, model.NewAppError("ToggleMuteChannel", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound)
  2829  		default:
  2830  			return nil, model.NewAppError("ToggleMuteChannel", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2831  		}
  2832  	}
  2833  
  2834  	member.SetChannelMuted(!member.IsChannelMuted())
  2835  
  2836  	member, err := a.updateChannelMember(member)
  2837  	if err != nil {
  2838  		return nil, err
  2839  	}
  2840  
  2841  	a.invalidateCacheForChannelMembersNotifyProps(member.ChannelId)
  2842  
  2843  	return member, nil
  2844  }
  2845  
  2846  func (a *App) setChannelsMuted(channelIds []string, userID string, muted bool) ([]*model.ChannelMember, *model.AppError) {
  2847  	members, nErr := a.Srv().Store.Channel().GetMembersByChannelIds(channelIds, userID)
  2848  	if nErr != nil {
  2849  		var appErr *model.AppError
  2850  		switch {
  2851  		case errors.As(nErr, &appErr):
  2852  			return nil, appErr
  2853  		default:
  2854  			return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2855  		}
  2856  	}
  2857  
  2858  	var membersToUpdate []*model.ChannelMember
  2859  	for _, member := range *members {
  2860  		if muted == member.IsChannelMuted() {
  2861  			continue
  2862  		}
  2863  
  2864  		updatedMember := member
  2865  		updatedMember.SetChannelMuted(muted)
  2866  
  2867  		membersToUpdate = append(membersToUpdate, &updatedMember)
  2868  	}
  2869  
  2870  	if len(membersToUpdate) == 0 {
  2871  		return nil, nil
  2872  	}
  2873  
  2874  	updated, nErr := a.Srv().Store.Channel().UpdateMultipleMembers(membersToUpdate)
  2875  	if nErr != nil {
  2876  		var appErr *model.AppError
  2877  		var nfErr *store.ErrNotFound
  2878  		switch {
  2879  		case errors.As(nErr, &appErr):
  2880  			return nil, appErr
  2881  		case errors.As(nErr, &nfErr):
  2882  			return nil, model.NewAppError("setChannelsMuted", MissingChannelMemberError, nil, nfErr.Error(), http.StatusNotFound)
  2883  		default:
  2884  			return nil, model.NewAppError("setChannelsMuted", "app.channel.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  2885  		}
  2886  	}
  2887  
  2888  	for _, member := range updated {
  2889  		a.invalidateCacheForChannelMembersNotifyProps(member.ChannelId)
  2890  
  2891  		evt := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", member.UserId, nil)
  2892  		evt.Add("channelMember", member.ToJson())
  2893  		a.Publish(evt)
  2894  	}
  2895  
  2896  	return updated, nil
  2897  }
  2898  
  2899  func (a *App) FillInChannelProps(channel *model.Channel) *model.AppError {
  2900  	return a.FillInChannelsProps(&model.ChannelList{channel})
  2901  }
  2902  
  2903  func (a *App) FillInChannelsProps(channelList *model.ChannelList) *model.AppError {
  2904  	// Group the channels by team and call GetChannelsByNames just once per team.
  2905  	channelsByTeam := make(map[string]model.ChannelList)
  2906  	for _, channel := range *channelList {
  2907  		channelsByTeam[channel.TeamId] = append(channelsByTeam[channel.TeamId], channel)
  2908  	}
  2909  
  2910  	for teamID, channelList := range channelsByTeam {
  2911  		allChannelMentions := make(map[string]bool)
  2912  		channelMentions := make(map[*model.Channel][]string, len(channelList))
  2913  
  2914  		// Collect mentions across the channels so as to query just once for this team.
  2915  		for _, channel := range channelList {
  2916  			channelMentions[channel] = model.ChannelMentions(channel.Header)
  2917  
  2918  			for _, channelMention := range channelMentions[channel] {
  2919  				allChannelMentions[channelMention] = true
  2920  			}
  2921  		}
  2922  
  2923  		allChannelMentionNames := make([]string, 0, len(allChannelMentions))
  2924  		for channelName := range allChannelMentions {
  2925  			allChannelMentionNames = append(allChannelMentionNames, channelName)
  2926  		}
  2927  
  2928  		if len(allChannelMentionNames) > 0 {
  2929  			mentionedChannels, err := a.GetChannelsByNames(allChannelMentionNames, teamID)
  2930  			if err != nil {
  2931  				return err
  2932  			}
  2933  
  2934  			mentionedChannelsByName := make(map[string]*model.Channel)
  2935  			for _, channel := range mentionedChannels {
  2936  				mentionedChannelsByName[channel.Name] = channel
  2937  			}
  2938  
  2939  			for _, channel := range channelList {
  2940  				channelMentionsProp := make(map[string]interface{}, len(channelMentions[channel]))
  2941  				for _, channelMention := range channelMentions[channel] {
  2942  					if mentioned, ok := mentionedChannelsByName[channelMention]; ok {
  2943  						if mentioned.Type == model.CHANNEL_OPEN {
  2944  							channelMentionsProp[mentioned.Name] = map[string]interface{}{
  2945  								"display_name": mentioned.DisplayName,
  2946  							}
  2947  						}
  2948  					}
  2949  				}
  2950  
  2951  				if len(channelMentionsProp) > 0 {
  2952  					channel.AddProp("channel_mentions", channelMentionsProp)
  2953  				} else if channel.Props != nil {
  2954  					delete(channel.Props, "channel_mentions")
  2955  				}
  2956  			}
  2957  		}
  2958  	}
  2959  
  2960  	return nil
  2961  }
  2962  
  2963  func (a *App) ClearChannelMembersCache(channelID string) {
  2964  	perPage := 100
  2965  	page := 0
  2966  
  2967  	for {
  2968  		channelMembers, err := a.Srv().Store.Channel().GetMembers(channelID, page*perPage, perPage)
  2969  		if err != nil {
  2970  			a.Log().Warn("error clearing cache for channel members", mlog.String("channel_id", channelID))
  2971  			break
  2972  		}
  2973  
  2974  		for _, channelMember := range *channelMembers {
  2975  			a.ClearSessionCacheForUser(channelMember.UserId)
  2976  
  2977  			message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", channelMember.UserId, nil)
  2978  			message.Add("channelMember", channelMember.ToJson())
  2979  			a.Publish(message)
  2980  		}
  2981  
  2982  		length := len(*(channelMembers))
  2983  		if length < perPage {
  2984  			break
  2985  		}
  2986  
  2987  		page++
  2988  	}
  2989  }
  2990  
  2991  func (a *App) GetMemberCountsByGroup(channelID string, includeTimezones bool) ([]*model.ChannelMemberCountByGroup, *model.AppError) {
  2992  	channelMemberCounts, err := a.Srv().Store.Channel().GetMemberCountsByGroup(channelID, includeTimezones)
  2993  	if err != nil {
  2994  		return nil, model.NewAppError("GetMemberCountsByGroup", "app.channel.get_member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  2995  	}
  2996  
  2997  	return channelMemberCounts, nil
  2998  }
  2999  
  3000  func (a *App) getDirectChannel(userID, otherUserID string) (*model.Channel, *model.AppError) {
  3001  	channel, nErr := a.Srv().Store.Channel().GetByName("", model.GetDMNameFromIds(userID, otherUserID), true)
  3002  	if nErr != nil {
  3003  		var nfErr *store.ErrNotFound
  3004  		if errors.As(nErr, &nfErr) {
  3005  			return nil, nil
  3006  		}
  3007  
  3008  		return nil, model.NewAppError("GetOrCreateDirectChannel", "web.incoming_webhook.channel.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  3009  	}
  3010  
  3011  	return channel, nil
  3012  }