github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/plugin_api.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  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"net/http"
    13  	"net/url"
    14  	"path/filepath"
    15  	"strings"
    16  
    17  	"github.com/mattermost/mattermost-server/v5/mlog"
    18  	"github.com/mattermost/mattermost-server/v5/model"
    19  	"github.com/mattermost/mattermost-server/v5/utils"
    20  )
    21  
    22  type PluginAPI struct {
    23  	id       string
    24  	app      *App
    25  	logger   *mlog.SugarLogger
    26  	manifest *model.Manifest
    27  }
    28  
    29  func NewPluginAPI(a *App, manifest *model.Manifest) *PluginAPI {
    30  	return &PluginAPI{
    31  		id:       manifest.Id,
    32  		manifest: manifest,
    33  		app:      a,
    34  		logger:   a.Log().With(mlog.String("plugin_id", manifest.Id)).Sugar(),
    35  	}
    36  }
    37  
    38  func (api *PluginAPI) LoadPluginConfiguration(dest interface{}) error {
    39  	finalConfig := make(map[string]interface{})
    40  
    41  	// First set final config to defaults
    42  	if api.manifest.SettingsSchema != nil {
    43  		for _, setting := range api.manifest.SettingsSchema.Settings {
    44  			finalConfig[strings.ToLower(setting.Key)] = setting.Default
    45  		}
    46  	}
    47  
    48  	// If we have settings given we override the defaults with them
    49  	for setting, value := range api.app.Config().PluginSettings.Plugins[api.id] {
    50  		finalConfig[strings.ToLower(setting)] = value
    51  	}
    52  
    53  	pluginSettingsJsonBytes, err := json.Marshal(finalConfig)
    54  	if err != nil {
    55  		api.logger.Error("Error marshaling config for plugin", mlog.Err(err))
    56  		return nil
    57  	}
    58  	err = json.Unmarshal(pluginSettingsJsonBytes, dest)
    59  	if err != nil {
    60  		api.logger.Error("Error unmarshaling config for plugin", mlog.Err(err))
    61  	}
    62  	return nil
    63  }
    64  
    65  func (api *PluginAPI) RegisterCommand(command *model.Command) error {
    66  	return api.app.RegisterPluginCommand(api.id, command)
    67  }
    68  
    69  func (api *PluginAPI) UnregisterCommand(teamID, trigger string) error {
    70  	api.app.UnregisterPluginCommand(api.id, teamID, trigger)
    71  	return nil
    72  }
    73  
    74  func (api *PluginAPI) ExecuteSlashCommand(commandArgs *model.CommandArgs) (*model.CommandResponse, error) {
    75  	user, appErr := api.app.GetUser(commandArgs.UserId)
    76  	if appErr != nil {
    77  		return nil, appErr
    78  	}
    79  	commandArgs.T = utils.GetUserTranslations(user.Locale)
    80  	commandArgs.SiteURL = api.app.GetSiteURL()
    81  	response, appErr := api.app.ExecuteCommand(commandArgs)
    82  	if appErr != nil {
    83  		return response, appErr
    84  	}
    85  	return response, nil
    86  }
    87  
    88  func (api *PluginAPI) GetSession(sessionId string) (*model.Session, *model.AppError) {
    89  	session, err := api.app.GetSessionById(sessionId)
    90  
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	return session, nil
    96  }
    97  
    98  func (api *PluginAPI) GetConfig() *model.Config {
    99  	return api.app.GetSanitizedConfig()
   100  }
   101  
   102  // GetUnsanitizedConfig gets the configuration for a system admin without removing secrets.
   103  func (api *PluginAPI) GetUnsanitizedConfig() *model.Config {
   104  	return api.app.Config().Clone()
   105  }
   106  
   107  func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError {
   108  	return api.app.SaveConfig(config, true)
   109  }
   110  
   111  func (api *PluginAPI) GetPluginConfig() map[string]interface{} {
   112  	cfg := api.app.GetSanitizedConfig()
   113  	if pluginConfig, isOk := cfg.PluginSettings.Plugins[api.manifest.Id]; isOk {
   114  		return pluginConfig
   115  	}
   116  	return map[string]interface{}{}
   117  }
   118  
   119  func (api *PluginAPI) SavePluginConfig(pluginConfig map[string]interface{}) *model.AppError {
   120  	cfg := api.app.GetSanitizedConfig()
   121  	cfg.PluginSettings.Plugins[api.manifest.Id] = pluginConfig
   122  	return api.app.SaveConfig(cfg, true)
   123  }
   124  
   125  func (api *PluginAPI) GetBundlePath() (string, error) {
   126  	bundlePath, err := filepath.Abs(filepath.Join(*api.GetConfig().PluginSettings.Directory, api.manifest.Id))
   127  	if err != nil {
   128  		return "", err
   129  	}
   130  
   131  	return bundlePath, err
   132  }
   133  
   134  func (api *PluginAPI) GetLicense() *model.License {
   135  	return api.app.Srv().License()
   136  }
   137  
   138  func (api *PluginAPI) GetServerVersion() string {
   139  	return model.CurrentVersion
   140  }
   141  
   142  func (api *PluginAPI) GetSystemInstallDate() (int64, *model.AppError) {
   143  	return api.app.Srv().getSystemInstallDate()
   144  }
   145  
   146  func (api *PluginAPI) GetDiagnosticId() string {
   147  	return api.app.TelemetryId()
   148  }
   149  
   150  func (api *PluginAPI) GetTelemetryId() string {
   151  	return api.app.TelemetryId()
   152  }
   153  
   154  func (api *PluginAPI) CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
   155  	return api.app.CreateTeam(team)
   156  }
   157  
   158  func (api *PluginAPI) DeleteTeam(teamID string) *model.AppError {
   159  	return api.app.SoftDeleteTeam(teamID)
   160  }
   161  
   162  func (api *PluginAPI) GetTeams() ([]*model.Team, *model.AppError) {
   163  	return api.app.GetAllTeams()
   164  }
   165  
   166  func (api *PluginAPI) GetTeam(teamID string) (*model.Team, *model.AppError) {
   167  	return api.app.GetTeam(teamID)
   168  }
   169  
   170  func (api *PluginAPI) SearchTeams(term string) ([]*model.Team, *model.AppError) {
   171  	teams, _, err := api.app.SearchAllTeams(&model.TeamSearch{Term: term})
   172  	return teams, err
   173  }
   174  
   175  func (api *PluginAPI) GetTeamByName(name string) (*model.Team, *model.AppError) {
   176  	return api.app.GetTeamByName(name)
   177  }
   178  
   179  func (api *PluginAPI) GetTeamsUnreadForUser(userID string) ([]*model.TeamUnread, *model.AppError) {
   180  	return api.app.GetTeamsUnreadForUser("", userID)
   181  }
   182  
   183  func (api *PluginAPI) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
   184  	return api.app.UpdateTeam(team)
   185  }
   186  
   187  func (api *PluginAPI) GetTeamsForUser(userID string) ([]*model.Team, *model.AppError) {
   188  	return api.app.GetTeamsForUser(userID)
   189  }
   190  
   191  func (api *PluginAPI) CreateTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) {
   192  	return api.app.AddTeamMember(teamID, userID)
   193  }
   194  
   195  func (api *PluginAPI) CreateTeamMembers(teamID string, userIDs []string, requestorId string) ([]*model.TeamMember, *model.AppError) {
   196  	members, err := api.app.AddTeamMembers(teamID, userIDs, requestorId, false)
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  	return model.TeamMembersWithErrorToTeamMembers(members), nil
   201  }
   202  
   203  func (api *PluginAPI) CreateTeamMembersGracefully(teamID string, userIDs []string, requestorId string) ([]*model.TeamMemberWithError, *model.AppError) {
   204  	return api.app.AddTeamMembers(teamID, userIDs, requestorId, true)
   205  }
   206  
   207  func (api *PluginAPI) DeleteTeamMember(teamID, userID, requestorId string) *model.AppError {
   208  	return api.app.RemoveUserFromTeam(teamID, userID, requestorId)
   209  }
   210  
   211  func (api *PluginAPI) GetTeamMembers(teamID string, page, perPage int) ([]*model.TeamMember, *model.AppError) {
   212  	return api.app.GetTeamMembers(teamID, page*perPage, perPage, nil)
   213  }
   214  
   215  func (api *PluginAPI) GetTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) {
   216  	return api.app.GetTeamMember(teamID, userID)
   217  }
   218  
   219  func (api *PluginAPI) GetTeamMembersForUser(userID string, page int, perPage int) ([]*model.TeamMember, *model.AppError) {
   220  	return api.app.GetTeamMembersForUserWithPagination(userID, page, perPage)
   221  }
   222  
   223  func (api *PluginAPI) UpdateTeamMemberRoles(teamID, userID, newRoles string) (*model.TeamMember, *model.AppError) {
   224  	return api.app.UpdateTeamMemberRoles(teamID, userID, newRoles)
   225  }
   226  
   227  func (api *PluginAPI) GetTeamStats(teamID string) (*model.TeamStats, *model.AppError) {
   228  	return api.app.GetTeamStats(teamID, nil)
   229  }
   230  
   231  func (api *PluginAPI) CreateUser(user *model.User) (*model.User, *model.AppError) {
   232  	return api.app.CreateUser(user)
   233  }
   234  
   235  func (api *PluginAPI) DeleteUser(userID string) *model.AppError {
   236  	user, err := api.app.GetUser(userID)
   237  	if err != nil {
   238  		return err
   239  	}
   240  	_, err = api.app.UpdateActive(user, false)
   241  	return err
   242  }
   243  
   244  func (api *PluginAPI) GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError) {
   245  	return api.app.GetUsers(options)
   246  }
   247  
   248  func (api *PluginAPI) GetUser(userID string) (*model.User, *model.AppError) {
   249  	return api.app.GetUser(userID)
   250  }
   251  
   252  func (api *PluginAPI) GetUserByEmail(email string) (*model.User, *model.AppError) {
   253  	return api.app.GetUserByEmail(email)
   254  }
   255  
   256  func (api *PluginAPI) GetUserByUsername(name string) (*model.User, *model.AppError) {
   257  	return api.app.GetUserByUsername(name)
   258  }
   259  
   260  func (api *PluginAPI) GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError) {
   261  	return api.app.GetUsersByUsernames(usernames, true, nil)
   262  }
   263  
   264  func (api *PluginAPI) GetUsersInTeam(teamID string, page int, perPage int) ([]*model.User, *model.AppError) {
   265  	options := &model.UserGetOptions{InTeamId: teamID, Page: page, PerPage: perPage}
   266  	return api.app.GetUsersInTeam(options)
   267  }
   268  
   269  func (api *PluginAPI) GetPreferencesForUser(userID string) ([]model.Preference, *model.AppError) {
   270  	return api.app.GetPreferencesForUser(userID)
   271  }
   272  
   273  func (api *PluginAPI) UpdatePreferencesForUser(userID string, preferences []model.Preference) *model.AppError {
   274  	return api.app.UpdatePreferences(userID, preferences)
   275  }
   276  
   277  func (api *PluginAPI) DeletePreferencesForUser(userID string, preferences []model.Preference) *model.AppError {
   278  	return api.app.DeletePreferences(userID, preferences)
   279  }
   280  
   281  func (api *PluginAPI) UpdateUser(user *model.User) (*model.User, *model.AppError) {
   282  	return api.app.UpdateUser(user, true)
   283  }
   284  
   285  func (api *PluginAPI) UpdateUserActive(userID string, active bool) *model.AppError {
   286  	return api.app.UpdateUserActive(userID, active)
   287  }
   288  
   289  func (api *PluginAPI) GetUserStatus(userID string) (*model.Status, *model.AppError) {
   290  	return api.app.GetStatus(userID)
   291  }
   292  
   293  func (api *PluginAPI) GetUserStatusesByIds(userIDs []string) ([]*model.Status, *model.AppError) {
   294  	return api.app.GetUserStatusesByIds(userIDs)
   295  }
   296  
   297  func (api *PluginAPI) UpdateUserStatus(userID, status string) (*model.Status, *model.AppError) {
   298  	switch status {
   299  	case model.STATUS_ONLINE:
   300  		api.app.SetStatusOnline(userID, true)
   301  	case model.STATUS_OFFLINE:
   302  		api.app.SetStatusOffline(userID, true)
   303  	case model.STATUS_AWAY:
   304  		api.app.SetStatusAwayIfNeeded(userID, true)
   305  	case model.STATUS_DND:
   306  		api.app.SetStatusDoNotDisturb(userID)
   307  	default:
   308  		return nil, model.NewAppError("UpdateUserStatus", "plugin.api.update_user_status.bad_status", nil, "unrecognized status", http.StatusBadRequest)
   309  	}
   310  
   311  	return api.app.GetStatus(userID)
   312  }
   313  
   314  func (api *PluginAPI) GetUsersInChannel(channelId, sortBy string, page, perPage int) ([]*model.User, *model.AppError) {
   315  	switch sortBy {
   316  	case model.CHANNEL_SORT_BY_USERNAME:
   317  		return api.app.GetUsersInChannel(&model.UserGetOptions{
   318  			InChannelId: channelId,
   319  			Page:        page,
   320  			PerPage:     perPage,
   321  		})
   322  	case model.CHANNEL_SORT_BY_STATUS:
   323  		return api.app.GetUsersInChannelByStatus(&model.UserGetOptions{
   324  			InChannelId: channelId,
   325  			Page:        page,
   326  			PerPage:     perPage,
   327  		})
   328  	default:
   329  		return nil, model.NewAppError("GetUsersInChannel", "plugin.api.get_users_in_channel", nil, "invalid sort option", http.StatusBadRequest)
   330  	}
   331  }
   332  
   333  func (api *PluginAPI) GetLDAPUserAttributes(userID string, attributes []string) (map[string]string, *model.AppError) {
   334  	if api.app.Ldap() == nil {
   335  		return nil, model.NewAppError("GetLdapUserAttributes", "ent.ldap.disabled.app_error", nil, "", http.StatusNotImplemented)
   336  	}
   337  
   338  	user, err := api.app.GetUser(userID)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	if user.AuthData == nil {
   344  		return map[string]string{}, nil
   345  	}
   346  
   347  	// Only bother running the query if the user's auth service is LDAP or it's SAML and sync is enabled.
   348  	if user.AuthService == model.USER_AUTH_SERVICE_LDAP ||
   349  		(user.AuthService == model.USER_AUTH_SERVICE_SAML && *api.app.Config().SamlSettings.EnableSyncWithLdap) {
   350  		return api.app.Ldap().GetUserAttributes(*user.AuthData, attributes)
   351  	}
   352  
   353  	return map[string]string{}, nil
   354  }
   355  
   356  func (api *PluginAPI) CreateChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
   357  	return api.app.CreateChannel(channel, false)
   358  }
   359  
   360  func (api *PluginAPI) DeleteChannel(channelId string) *model.AppError {
   361  	channel, err := api.app.GetChannel(channelId)
   362  	if err != nil {
   363  		return err
   364  	}
   365  	return api.app.DeleteChannel(channel, "")
   366  }
   367  
   368  func (api *PluginAPI) GetPublicChannelsForTeam(teamID string, page, perPage int) ([]*model.Channel, *model.AppError) {
   369  	channels, err := api.app.GetPublicChannelsForTeam(teamID, page*perPage, perPage)
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  	return *channels, err
   374  }
   375  
   376  func (api *PluginAPI) GetChannel(channelId string) (*model.Channel, *model.AppError) {
   377  	return api.app.GetChannel(channelId)
   378  }
   379  
   380  func (api *PluginAPI) GetChannelByName(teamID, name string, includeDeleted bool) (*model.Channel, *model.AppError) {
   381  	return api.app.GetChannelByName(name, teamID, includeDeleted)
   382  }
   383  
   384  func (api *PluginAPI) GetChannelByNameForTeamName(teamName, channelName string, includeDeleted bool) (*model.Channel, *model.AppError) {
   385  	return api.app.GetChannelByNameForTeamName(channelName, teamName, includeDeleted)
   386  }
   387  
   388  func (api *PluginAPI) GetChannelsForTeamForUser(teamID, userID string, includeDeleted bool) ([]*model.Channel, *model.AppError) {
   389  	channels, err := api.app.GetChannelsForUser(teamID, userID, includeDeleted, 0)
   390  	if err != nil {
   391  		return nil, err
   392  	}
   393  	return *channels, err
   394  }
   395  
   396  func (api *PluginAPI) GetChannelStats(channelId string) (*model.ChannelStats, *model.AppError) {
   397  	memberCount, err := api.app.GetChannelMemberCount(channelId)
   398  	if err != nil {
   399  		return nil, err
   400  	}
   401  	guestCount, err := api.app.GetChannelMemberCount(channelId)
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  	return &model.ChannelStats{ChannelId: channelId, MemberCount: memberCount, GuestCount: guestCount}, nil
   406  }
   407  
   408  func (api *PluginAPI) GetDirectChannel(userID1, userID2 string) (*model.Channel, *model.AppError) {
   409  	return api.app.GetOrCreateDirectChannel(userID1, userID2)
   410  }
   411  
   412  func (api *PluginAPI) GetGroupChannel(userIDs []string) (*model.Channel, *model.AppError) {
   413  	return api.app.CreateGroupChannel(userIDs, "")
   414  }
   415  
   416  func (api *PluginAPI) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) {
   417  	return api.app.UpdateChannel(channel)
   418  }
   419  
   420  func (api *PluginAPI) SearchChannels(teamID string, term string) ([]*model.Channel, *model.AppError) {
   421  	channels, err := api.app.SearchChannels(teamID, term)
   422  	if err != nil {
   423  		return nil, err
   424  	}
   425  	return *channels, err
   426  }
   427  
   428  func (api *PluginAPI) SearchUsers(search *model.UserSearch) ([]*model.User, *model.AppError) {
   429  	pluginSearchUsersOptions := &model.UserSearchOptions{
   430  		IsAdmin:       true,
   431  		AllowInactive: search.AllowInactive,
   432  		Limit:         search.Limit,
   433  	}
   434  	return api.app.SearchUsers(search, pluginSearchUsersOptions)
   435  }
   436  
   437  func (api *PluginAPI) SearchPostsInTeam(teamID string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError) {
   438  	postList, err := api.app.SearchPostsInTeam(teamID, paramsList)
   439  	if err != nil {
   440  		return nil, err
   441  	}
   442  	return postList.ToSlice(), nil
   443  }
   444  
   445  func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, searchParams model.SearchParameter) (*model.PostSearchResults, *model.AppError) {
   446  	var terms string
   447  	if searchParams.Terms != nil {
   448  		terms = *searchParams.Terms
   449  	}
   450  
   451  	timeZoneOffset := 0
   452  	if searchParams.TimeZoneOffset != nil {
   453  		timeZoneOffset = *searchParams.TimeZoneOffset
   454  	}
   455  
   456  	isOrSearch := false
   457  	if searchParams.IsOrSearch != nil {
   458  		isOrSearch = *searchParams.IsOrSearch
   459  	}
   460  
   461  	page := 0
   462  	if searchParams.Page != nil {
   463  		page = *searchParams.Page
   464  	}
   465  
   466  	perPage := 100
   467  	if searchParams.PerPage != nil {
   468  		perPage = *searchParams.PerPage
   469  	}
   470  
   471  	includeDeletedChannels := false
   472  	if searchParams.IncludeDeletedChannels != nil {
   473  		includeDeletedChannels = *searchParams.IncludeDeletedChannels
   474  	}
   475  
   476  	return api.app.SearchPostsInTeamForUser(terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
   477  }
   478  
   479  func (api *PluginAPI) AddChannelMember(channelId, userID string) (*model.ChannelMember, *model.AppError) {
   480  	// For now, don't allow overriding these via the plugin API.
   481  	userRequestorId := ""
   482  	postRootId := ""
   483  
   484  	channel, err := api.GetChannel(channelId)
   485  	if err != nil {
   486  		return nil, err
   487  	}
   488  
   489  	return api.app.AddChannelMember(userID, channel, userRequestorId, postRootId)
   490  }
   491  
   492  func (api *PluginAPI) AddUserToChannel(channelId, userID, asUserId string) (*model.ChannelMember, *model.AppError) {
   493  	postRootId := ""
   494  
   495  	channel, err := api.GetChannel(channelId)
   496  	if err != nil {
   497  		return nil, err
   498  	}
   499  
   500  	return api.app.AddChannelMember(userID, channel, asUserId, postRootId)
   501  }
   502  
   503  func (api *PluginAPI) GetChannelMember(channelId, userID string) (*model.ChannelMember, *model.AppError) {
   504  	return api.app.GetChannelMember(channelId, userID)
   505  }
   506  
   507  func (api *PluginAPI) GetChannelMembers(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError) {
   508  	return api.app.GetChannelMembersPage(channelId, page, perPage)
   509  }
   510  
   511  func (api *PluginAPI) GetChannelMembersByIds(channelId string, userIDs []string) (*model.ChannelMembers, *model.AppError) {
   512  	return api.app.GetChannelMembersByIds(channelId, userIDs)
   513  }
   514  
   515  func (api *PluginAPI) GetChannelMembersForUser(teamID, userID string, page, perPage int) ([]*model.ChannelMember, *model.AppError) {
   516  	return api.app.GetChannelMembersForUserWithPagination(teamID, userID, page, perPage)
   517  }
   518  
   519  func (api *PluginAPI) UpdateChannelMemberRoles(channelId, userID, newRoles string) (*model.ChannelMember, *model.AppError) {
   520  	return api.app.UpdateChannelMemberRoles(channelId, userID, newRoles)
   521  }
   522  
   523  func (api *PluginAPI) UpdateChannelMemberNotifications(channelId, userID string, notifications map[string]string) (*model.ChannelMember, *model.AppError) {
   524  	return api.app.UpdateChannelMemberNotifyProps(notifications, channelId, userID)
   525  }
   526  
   527  func (api *PluginAPI) DeleteChannelMember(channelId, userID string) *model.AppError {
   528  	return api.app.LeaveChannel(channelId, userID)
   529  }
   530  
   531  func (api *PluginAPI) GetGroup(groupId string) (*model.Group, *model.AppError) {
   532  	return api.app.GetGroup(groupId)
   533  }
   534  
   535  func (api *PluginAPI) GetGroupByName(name string) (*model.Group, *model.AppError) {
   536  	return api.app.GetGroupByName(name, model.GroupSearchOpts{})
   537  }
   538  
   539  func (api *PluginAPI) GetGroupsForUser(userID string) ([]*model.Group, *model.AppError) {
   540  	return api.app.GetGroupsByUserId(userID)
   541  }
   542  
   543  func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
   544  	return api.app.CreatePostMissingChannel(post, true)
   545  }
   546  
   547  func (api *PluginAPI) AddReaction(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
   548  	return api.app.SaveReactionForPost(reaction)
   549  }
   550  
   551  func (api *PluginAPI) RemoveReaction(reaction *model.Reaction) *model.AppError {
   552  	return api.app.DeleteReactionForPost(reaction)
   553  }
   554  
   555  func (api *PluginAPI) GetReactions(postId string) ([]*model.Reaction, *model.AppError) {
   556  	return api.app.GetReactionsForPost(postId)
   557  }
   558  
   559  func (api *PluginAPI) SendEphemeralPost(userID string, post *model.Post) *model.Post {
   560  	return api.app.SendEphemeralPost(userID, post)
   561  }
   562  
   563  func (api *PluginAPI) UpdateEphemeralPost(userID string, post *model.Post) *model.Post {
   564  	return api.app.UpdateEphemeralPost(userID, post)
   565  }
   566  
   567  func (api *PluginAPI) DeleteEphemeralPost(userID, postId string) {
   568  	api.app.DeleteEphemeralPost(userID, postId)
   569  }
   570  
   571  func (api *PluginAPI) DeletePost(postId string) *model.AppError {
   572  	_, err := api.app.DeletePost(postId, api.id)
   573  	return err
   574  }
   575  
   576  func (api *PluginAPI) GetPostThread(postId string) (*model.PostList, *model.AppError) {
   577  	return api.app.GetPostThread(postId, false, false, false)
   578  }
   579  
   580  func (api *PluginAPI) GetPost(postId string) (*model.Post, *model.AppError) {
   581  	return api.app.GetSinglePost(postId)
   582  }
   583  
   584  func (api *PluginAPI) GetPostsSince(channelId string, time int64) (*model.PostList, *model.AppError) {
   585  	return api.app.GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: time})
   586  }
   587  
   588  func (api *PluginAPI) GetPostsAfter(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError) {
   589  	return api.app.GetPostsAfterPost(model.GetPostsOptions{ChannelId: channelId, PostId: postId, Page: page, PerPage: perPage})
   590  }
   591  
   592  func (api *PluginAPI) GetPostsBefore(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError) {
   593  	return api.app.GetPostsBeforePost(model.GetPostsOptions{ChannelId: channelId, PostId: postId, Page: page, PerPage: perPage})
   594  }
   595  
   596  func (api *PluginAPI) GetPostsForChannel(channelId string, page, perPage int) (*model.PostList, *model.AppError) {
   597  	return api.app.GetPostsPage(model.GetPostsOptions{ChannelId: channelId, Page: page, PerPage: perPage})
   598  }
   599  
   600  func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) {
   601  	return api.app.UpdatePost(post, false)
   602  }
   603  
   604  func (api *PluginAPI) GetProfileImage(userID string) ([]byte, *model.AppError) {
   605  	user, err := api.app.GetUser(userID)
   606  	if err != nil {
   607  		return nil, err
   608  	}
   609  
   610  	data, _, err := api.app.GetProfileImage(user)
   611  	return data, err
   612  }
   613  
   614  func (api *PluginAPI) SetProfileImage(userID string, data []byte) *model.AppError {
   615  	_, err := api.app.GetUser(userID)
   616  	if err != nil {
   617  		return err
   618  	}
   619  
   620  	return api.app.SetProfileImageFromFile(userID, bytes.NewReader(data))
   621  }
   622  
   623  func (api *PluginAPI) GetEmojiList(sortBy string, page, perPage int) ([]*model.Emoji, *model.AppError) {
   624  	return api.app.GetEmojiList(page, perPage, sortBy)
   625  }
   626  
   627  func (api *PluginAPI) GetEmojiByName(name string) (*model.Emoji, *model.AppError) {
   628  	return api.app.GetEmojiByName(name)
   629  }
   630  
   631  func (api *PluginAPI) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) {
   632  	return api.app.GetEmoji(emojiId)
   633  }
   634  
   635  func (api *PluginAPI) CopyFileInfos(userID string, fileIds []string) ([]string, *model.AppError) {
   636  	return api.app.CopyFileInfos(userID, fileIds)
   637  }
   638  
   639  func (api *PluginAPI) GetFileInfo(fileId string) (*model.FileInfo, *model.AppError) {
   640  	return api.app.GetFileInfo(fileId)
   641  }
   642  
   643  func (api *PluginAPI) GetFileInfos(page, perPage int, opt *model.GetFileInfosOptions) ([]*model.FileInfo, *model.AppError) {
   644  	return api.app.GetFileInfos(page, perPage, opt)
   645  }
   646  
   647  func (api *PluginAPI) GetFileLink(fileId string) (string, *model.AppError) {
   648  	if !*api.app.Config().FileSettings.EnablePublicLink {
   649  		return "", model.NewAppError("GetFileLink", "plugin_api.get_file_link.disabled.app_error", nil, "", http.StatusNotImplemented)
   650  	}
   651  
   652  	info, err := api.app.GetFileInfo(fileId)
   653  	if err != nil {
   654  		return "", err
   655  	}
   656  
   657  	if info.PostId == "" {
   658  		return "", model.NewAppError("GetFileLink", "plugin_api.get_file_link.no_post.app_error", nil, "file_id="+info.Id, http.StatusBadRequest)
   659  	}
   660  
   661  	return api.app.GeneratePublicLink(api.app.GetSiteURL(), info), nil
   662  }
   663  
   664  func (api *PluginAPI) ReadFile(path string) ([]byte, *model.AppError) {
   665  	return api.app.ReadFile(path)
   666  }
   667  
   668  func (api *PluginAPI) GetFile(fileId string) ([]byte, *model.AppError) {
   669  	return api.app.GetFile(fileId)
   670  }
   671  
   672  func (api *PluginAPI) UploadFile(data []byte, channelId string, filename string) (*model.FileInfo, *model.AppError) {
   673  	return api.app.UploadFile(data, channelId, filename)
   674  }
   675  
   676  func (api *PluginAPI) GetEmojiImage(emojiId string) ([]byte, string, *model.AppError) {
   677  	return api.app.GetEmojiImage(emojiId)
   678  }
   679  
   680  func (api *PluginAPI) GetTeamIcon(teamID string) ([]byte, *model.AppError) {
   681  	team, err := api.app.GetTeam(teamID)
   682  	if err != nil {
   683  		return nil, err
   684  	}
   685  
   686  	data, err := api.app.GetTeamIcon(team)
   687  	if err != nil {
   688  		return nil, err
   689  	}
   690  	return data, nil
   691  }
   692  
   693  func (api *PluginAPI) SetTeamIcon(teamID string, data []byte) *model.AppError {
   694  	team, err := api.app.GetTeam(teamID)
   695  	if err != nil {
   696  		return err
   697  	}
   698  
   699  	return api.app.SetTeamIconFromFile(team, bytes.NewReader(data))
   700  }
   701  
   702  func (api *PluginAPI) OpenInteractiveDialog(dialog model.OpenDialogRequest) *model.AppError {
   703  	return api.app.OpenInteractiveDialog(dialog)
   704  }
   705  
   706  func (api *PluginAPI) RemoveTeamIcon(teamID string) *model.AppError {
   707  	_, err := api.app.GetTeam(teamID)
   708  	if err != nil {
   709  		return err
   710  	}
   711  
   712  	err = api.app.RemoveTeamIcon(teamID)
   713  	if err != nil {
   714  		return err
   715  	}
   716  	return nil
   717  }
   718  
   719  // Mail Section
   720  
   721  func (api *PluginAPI) SendMail(to, subject, htmlBody string) *model.AppError {
   722  	if to == "" {
   723  		return model.NewAppError("SendMail", "plugin_api.send_mail.missing_to", nil, "", http.StatusBadRequest)
   724  	}
   725  
   726  	if subject == "" {
   727  		return model.NewAppError("SendMail", "plugin_api.send_mail.missing_subject", nil, "", http.StatusBadRequest)
   728  	}
   729  
   730  	if htmlBody == "" {
   731  		return model.NewAppError("SendMail", "plugin_api.send_mail.missing_htmlbody", nil, "", http.StatusBadRequest)
   732  	}
   733  
   734  	if err := api.app.Srv().EmailService.sendNotificationMail(to, subject, htmlBody); err != nil {
   735  		return model.NewAppError("SendMail", "plugin_api.send_mail.missing_htmlbody", nil, err.Error(), http.StatusInternalServerError)
   736  	}
   737  
   738  	return nil
   739  }
   740  
   741  // Plugin Section
   742  
   743  func (api *PluginAPI) GetPlugins() ([]*model.Manifest, *model.AppError) {
   744  	plugins, err := api.app.GetPlugins()
   745  	if err != nil {
   746  		return nil, err
   747  	}
   748  	var manifests []*model.Manifest
   749  	for _, manifest := range plugins.Active {
   750  		manifests = append(manifests, &manifest.Manifest)
   751  	}
   752  	for _, manifest := range plugins.Inactive {
   753  		manifests = append(manifests, &manifest.Manifest)
   754  	}
   755  	return manifests, nil
   756  }
   757  
   758  func (api *PluginAPI) EnablePlugin(id string) *model.AppError {
   759  	return api.app.EnablePlugin(id)
   760  }
   761  
   762  func (api *PluginAPI) DisablePlugin(id string) *model.AppError {
   763  	return api.app.DisablePlugin(id)
   764  }
   765  
   766  func (api *PluginAPI) RemovePlugin(id string) *model.AppError {
   767  	return api.app.RemovePlugin(id)
   768  }
   769  
   770  func (api *PluginAPI) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) {
   771  	return api.app.GetPluginStatus(id)
   772  }
   773  
   774  func (api *PluginAPI) InstallPlugin(file io.Reader, replace bool) (*model.Manifest, *model.AppError) {
   775  	if !*api.app.Config().PluginSettings.Enable || !*api.app.Config().PluginSettings.EnableUploads {
   776  		return nil, model.NewAppError("installPlugin", "app.plugin.upload_disabled.app_error", nil, "", http.StatusNotImplemented)
   777  	}
   778  
   779  	fileBuffer, err := ioutil.ReadAll(file)
   780  	if err != nil {
   781  		return nil, model.NewAppError("InstallPlugin", "api.plugin.upload.file.app_error", nil, "", http.StatusBadRequest)
   782  	}
   783  
   784  	return api.app.InstallPlugin(bytes.NewReader(fileBuffer), replace)
   785  }
   786  
   787  // KV Store Section
   788  
   789  func (api *PluginAPI) KVSetWithOptions(key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError) {
   790  	return api.app.SetPluginKeyWithOptions(api.id, key, value, options)
   791  }
   792  
   793  func (api *PluginAPI) KVSet(key string, value []byte) *model.AppError {
   794  	return api.app.SetPluginKey(api.id, key, value)
   795  }
   796  
   797  func (api *PluginAPI) KVCompareAndSet(key string, oldValue, newValue []byte) (bool, *model.AppError) {
   798  	return api.app.CompareAndSetPluginKey(api.id, key, oldValue, newValue)
   799  }
   800  
   801  func (api *PluginAPI) KVCompareAndDelete(key string, oldValue []byte) (bool, *model.AppError) {
   802  	return api.app.CompareAndDeletePluginKey(api.id, key, oldValue)
   803  }
   804  
   805  func (api *PluginAPI) KVSetWithExpiry(key string, value []byte, expireInSeconds int64) *model.AppError {
   806  	return api.app.SetPluginKeyWithExpiry(api.id, key, value, expireInSeconds)
   807  }
   808  
   809  func (api *PluginAPI) KVGet(key string) ([]byte, *model.AppError) {
   810  	return api.app.GetPluginKey(api.id, key)
   811  }
   812  
   813  func (api *PluginAPI) KVDelete(key string) *model.AppError {
   814  	return api.app.DeletePluginKey(api.id, key)
   815  }
   816  
   817  func (api *PluginAPI) KVDeleteAll() *model.AppError {
   818  	return api.app.DeleteAllKeysForPlugin(api.id)
   819  }
   820  
   821  func (api *PluginAPI) KVList(page, perPage int) ([]string, *model.AppError) {
   822  	return api.app.ListPluginKeys(api.id, page, perPage)
   823  }
   824  
   825  func (api *PluginAPI) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *model.WebsocketBroadcast) {
   826  	ev := model.NewWebSocketEvent(fmt.Sprintf("custom_%v_%v", api.id, event), "", "", "", nil)
   827  	ev = ev.SetBroadcast(broadcast).SetData(payload)
   828  	api.app.Publish(ev)
   829  }
   830  
   831  func (api *PluginAPI) HasPermissionTo(userID string, permission *model.Permission) bool {
   832  	return api.app.HasPermissionTo(userID, permission)
   833  }
   834  
   835  func (api *PluginAPI) HasPermissionToTeam(userID, teamID string, permission *model.Permission) bool {
   836  	return api.app.HasPermissionToTeam(userID, teamID, permission)
   837  }
   838  
   839  func (api *PluginAPI) HasPermissionToChannel(userID, channelId string, permission *model.Permission) bool {
   840  	return api.app.HasPermissionToChannel(userID, channelId, permission)
   841  }
   842  
   843  func (api *PluginAPI) LogDebug(msg string, keyValuePairs ...interface{}) {
   844  	api.logger.Debug(msg, keyValuePairs...)
   845  }
   846  func (api *PluginAPI) LogInfo(msg string, keyValuePairs ...interface{}) {
   847  	api.logger.Info(msg, keyValuePairs...)
   848  }
   849  func (api *PluginAPI) LogError(msg string, keyValuePairs ...interface{}) {
   850  	api.logger.Error(msg, keyValuePairs...)
   851  }
   852  func (api *PluginAPI) LogWarn(msg string, keyValuePairs ...interface{}) {
   853  	api.logger.Warn(msg, keyValuePairs...)
   854  }
   855  
   856  func (api *PluginAPI) CreateBot(bot *model.Bot) (*model.Bot, *model.AppError) {
   857  	// Bots created by a plugin should use the plugin's ID for the creator field, unless
   858  	// otherwise specified by the plugin.
   859  	if bot.OwnerId == "" {
   860  		bot.OwnerId = api.id
   861  	}
   862  	// Bots cannot be owners of other bots
   863  	if user, err := api.app.GetUser(bot.OwnerId); err == nil {
   864  		if user.IsBot {
   865  			return nil, model.NewAppError("CreateBot", "plugin_api.bot_cant_create_bot", nil, "", http.StatusBadRequest)
   866  		}
   867  	}
   868  
   869  	return api.app.CreateBot(bot)
   870  }
   871  
   872  func (api *PluginAPI) PatchBot(userID string, botPatch *model.BotPatch) (*model.Bot, *model.AppError) {
   873  	return api.app.PatchBot(userID, botPatch)
   874  }
   875  
   876  func (api *PluginAPI) GetBot(userID string, includeDeleted bool) (*model.Bot, *model.AppError) {
   877  	return api.app.GetBot(userID, includeDeleted)
   878  }
   879  
   880  func (api *PluginAPI) GetBots(options *model.BotGetOptions) ([]*model.Bot, *model.AppError) {
   881  	bots, err := api.app.GetBots(options)
   882  
   883  	return []*model.Bot(bots), err
   884  }
   885  
   886  func (api *PluginAPI) UpdateBotActive(userID string, active bool) (*model.Bot, *model.AppError) {
   887  	return api.app.UpdateBotActive(userID, active)
   888  }
   889  
   890  func (api *PluginAPI) PermanentDeleteBot(userID string) *model.AppError {
   891  	return api.app.PermanentDeleteBot(userID)
   892  }
   893  
   894  func (api *PluginAPI) GetBotIconImage(userID string) ([]byte, *model.AppError) {
   895  	if _, err := api.app.GetBot(userID, true); err != nil {
   896  		return nil, err
   897  	}
   898  
   899  	return api.app.GetBotIconImage(userID)
   900  }
   901  
   902  func (api *PluginAPI) SetBotIconImage(userID string, data []byte) *model.AppError {
   903  	if _, err := api.app.GetBot(userID, true); err != nil {
   904  		return err
   905  	}
   906  
   907  	return api.app.SetBotIconImage(userID, bytes.NewReader(data))
   908  }
   909  
   910  func (api *PluginAPI) DeleteBotIconImage(userID string) *model.AppError {
   911  	if _, err := api.app.GetBot(userID, true); err != nil {
   912  		return err
   913  	}
   914  
   915  	return api.app.DeleteBotIconImage(userID)
   916  }
   917  
   918  func (api *PluginAPI) PublishUserTyping(userID, channelId, parentId string) *model.AppError {
   919  	return api.app.PublishUserTyping(userID, channelId, parentId)
   920  }
   921  
   922  func (api *PluginAPI) PluginHTTP(request *http.Request) *http.Response {
   923  	split := strings.SplitN(request.URL.Path, "/", 3)
   924  	if len(split) != 3 {
   925  		return &http.Response{
   926  			StatusCode: http.StatusBadRequest,
   927  			Body:       ioutil.NopCloser(bytes.NewBufferString("Not enough URL. Form of URL should be /<pluginid>/*")),
   928  		}
   929  	}
   930  	destinationPluginId := split[1]
   931  	newURL, err := url.Parse("/" + split[2])
   932  	newURL.RawQuery = request.URL.Query().Encode()
   933  	request.URL = newURL
   934  	if destinationPluginId == "" || err != nil {
   935  		message := "No plugin specified. Form of URL should be /<pluginid>/*"
   936  		if err != nil {
   937  			message = "Form of URL should be /<pluginid>/* Error: " + err.Error()
   938  		}
   939  		return &http.Response{
   940  			StatusCode: http.StatusBadRequest,
   941  			Body:       ioutil.NopCloser(bytes.NewBufferString(message)),
   942  		}
   943  	}
   944  	responseTransfer := &PluginResponseWriter{}
   945  	api.app.ServeInterPluginRequest(responseTransfer, request, api.id, destinationPluginId)
   946  	return responseTransfer.GenerateResponse()
   947  }
   948  
   949  func (api *PluginAPI) CreateCommand(cmd *model.Command) (*model.Command, error) {
   950  	cmd.CreatorId = ""
   951  	cmd.PluginId = api.id
   952  
   953  	cmd, appErr := api.app.createCommand(cmd)
   954  
   955  	if appErr != nil {
   956  		return cmd, appErr
   957  	}
   958  
   959  	return cmd, nil
   960  }
   961  
   962  func (api *PluginAPI) ListCommands(teamID string) ([]*model.Command, error) {
   963  	ret := make([]*model.Command, 0)
   964  
   965  	cmds, err := api.ListPluginCommands(teamID)
   966  	if err != nil {
   967  		return nil, err
   968  	}
   969  	ret = append(ret, cmds...)
   970  
   971  	cmds, err = api.ListBuiltInCommands()
   972  	if err != nil {
   973  		return nil, err
   974  	}
   975  	ret = append(ret, cmds...)
   976  
   977  	cmds, err = api.ListCustomCommands(teamID)
   978  	if err != nil {
   979  		return nil, err
   980  	}
   981  	ret = append(ret, cmds...)
   982  
   983  	return ret, nil
   984  }
   985  
   986  func (api *PluginAPI) ListCustomCommands(teamID string) ([]*model.Command, error) {
   987  	// Plugins are allowed to bypass the a.Config().ServiceSettings.EnableCommands setting.
   988  	return api.app.Srv().Store.Command().GetByTeam(teamID)
   989  }
   990  
   991  func (api *PluginAPI) ListPluginCommands(teamID string) ([]*model.Command, error) {
   992  	commands := make([]*model.Command, 0)
   993  	seen := make(map[string]bool)
   994  
   995  	for _, cmd := range api.app.PluginCommandsForTeam(teamID) {
   996  		if !seen[cmd.Trigger] {
   997  			seen[cmd.Trigger] = true
   998  			commands = append(commands, cmd)
   999  		}
  1000  	}
  1001  
  1002  	return commands, nil
  1003  }
  1004  
  1005  func (api *PluginAPI) ListBuiltInCommands() ([]*model.Command, error) {
  1006  	commands := make([]*model.Command, 0)
  1007  	seen := make(map[string]bool)
  1008  
  1009  	for _, value := range commandProviders {
  1010  		if cmd := value.GetCommand(api.app, utils.T); cmd != nil {
  1011  			cpy := *cmd
  1012  			if cpy.AutoComplete && !seen[cpy.Trigger] {
  1013  				cpy.Sanitize()
  1014  				seen[cpy.Trigger] = true
  1015  				commands = append(commands, &cpy)
  1016  			}
  1017  		}
  1018  	}
  1019  
  1020  	return commands, nil
  1021  }
  1022  
  1023  func (api *PluginAPI) GetCommand(commandID string) (*model.Command, error) {
  1024  	return api.app.Srv().Store.Command().Get(commandID)
  1025  }
  1026  
  1027  func (api *PluginAPI) UpdateCommand(commandID string, updatedCmd *model.Command) (*model.Command, error) {
  1028  	oldCmd, err := api.GetCommand(commandID)
  1029  	if err != nil {
  1030  		return nil, err
  1031  	}
  1032  
  1033  	updatedCmd.Trigger = strings.ToLower(updatedCmd.Trigger)
  1034  	updatedCmd.Id = oldCmd.Id
  1035  	updatedCmd.Token = oldCmd.Token
  1036  	updatedCmd.CreateAt = oldCmd.CreateAt
  1037  	updatedCmd.UpdateAt = model.GetMillis()
  1038  	updatedCmd.DeleteAt = oldCmd.DeleteAt
  1039  	updatedCmd.PluginId = api.id
  1040  	if updatedCmd.TeamId == "" {
  1041  		updatedCmd.TeamId = oldCmd.TeamId
  1042  	}
  1043  
  1044  	return api.app.Srv().Store.Command().Update(updatedCmd)
  1045  }
  1046  
  1047  func (api *PluginAPI) DeleteCommand(commandID string) error {
  1048  	err := api.app.Srv().Store.Command().Delete(commandID, model.GetMillis())
  1049  	if err != nil {
  1050  		return err
  1051  	}
  1052  
  1053  	return nil
  1054  }