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