From 1e5c432e1029601a664454388ae366ef69618d62 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 25 Jun 2018 12:33:13 -0700 Subject: MM-10702 Moving plugins to use hashicorp go-plugin. (#8978) * Moving plugins to use hashicorp go-plugin. * Tweaks from feedback. --- app/plugin_api.go | 146 +++++------------------------------------------------- 1 file changed, 13 insertions(+), 133 deletions(-) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index 06eeee146..ffb8cccd6 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -5,27 +5,22 @@ package app import ( "encoding/json" - "net/http" - "strings" - "github.com/gorilla/mux" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/utils" - - "github.com/mattermost/mattermost-server/plugin" ) type PluginAPI struct { - id string - app *App - keyValueStore *PluginKeyValueStore -} - -type PluginKeyValueStore struct { id string app *App } +func NewPluginAPI(a *App, manifest *model.Manifest) *PluginAPI { + return &PluginAPI{ + id: manifest.Id, + app: a, + } +} + func (api *PluginAPI) LoadPluginConfiguration(dest interface{}) error { if b, err := json.Marshal(api.app.Config().PluginSettings.Plugins[api.id]); err != nil { return err @@ -170,129 +165,14 @@ func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError return api.app.UpdatePost(post, false) } -func (api *PluginAPI) KeyValueStore() plugin.KeyValueStore { - return api.keyValueStore -} - -func (s *PluginKeyValueStore) Set(key string, value []byte) *model.AppError { - return s.app.SetPluginKey(s.id, key, value) +func (api *PluginAPI) KVSet(key string, value []byte) *model.AppError { + return api.app.SetPluginKey(api.id, key, value) } -func (s *PluginKeyValueStore) Get(key string) ([]byte, *model.AppError) { - return s.app.GetPluginKey(s.id, key) -} - -func (s *PluginKeyValueStore) Delete(key string) *model.AppError { - return s.app.DeletePluginKey(s.id, key) -} - -type BuiltInPluginAPI struct { - id string - router *mux.Router - app *App -} - -func (api *BuiltInPluginAPI) LoadPluginConfiguration(dest interface{}) error { - if b, err := json.Marshal(api.app.Config().PluginSettings.Plugins[api.id]); err != nil { - return err - } else { - return json.Unmarshal(b, dest) - } -} - -func (api *BuiltInPluginAPI) PluginRouter() *mux.Router { - return api.router -} - -func (api *BuiltInPluginAPI) GetTeamByName(name string) (*model.Team, *model.AppError) { - return api.app.GetTeamByName(name) -} - -func (api *BuiltInPluginAPI) GetUserByName(name string) (*model.User, *model.AppError) { - return api.app.GetUserByUsername(name) -} - -func (api *BuiltInPluginAPI) GetChannelByName(teamId, name string) (*model.Channel, *model.AppError) { - return api.app.GetChannelByName(name, teamId) -} - -func (api *BuiltInPluginAPI) GetDirectChannel(userId1, userId2 string) (*model.Channel, *model.AppError) { - return api.app.GetDirectChannel(userId1, userId2) +func (api *PluginAPI) KVGet(key string) ([]byte, *model.AppError) { + return api.app.GetPluginKey(api.id, key) } -func (api *BuiltInPluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) { - return api.app.CreatePostMissingChannel(post, true) -} - -func (api *BuiltInPluginAPI) GetLdapUserAttributes(userId string, attributes []string) (map[string]string, *model.AppError) { - if api.app.Ldap == nil { - return nil, model.NewAppError("GetLdapUserAttributes", "ent.ldap.disabled.app_error", nil, "", http.StatusNotImplemented) - } - - user, err := api.app.GetUser(userId) - if err != nil { - return nil, err - } - - if user.AuthData == nil { - return map[string]string{}, nil - } - - return api.app.Ldap.GetUserAttributes(*user.AuthData, attributes) -} - -func (api *BuiltInPluginAPI) GetSessionFromRequest(r *http.Request) (*model.Session, *model.AppError) { - token := "" - isTokenFromQueryString := false - - // Attempt to parse token out of the header - authHeader := r.Header.Get(model.HEADER_AUTH) - if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == model.HEADER_BEARER { - // Default session token - token = authHeader[7:] - - } else if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == model.HEADER_TOKEN { - // OAuth token - token = authHeader[6:] - } - - // Attempt to parse the token from the cookie - if len(token) == 0 { - if cookie, err := r.Cookie(model.SESSION_COOKIE_TOKEN); err == nil { - token = cookie.Value - - if r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML { - return nil, model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token+" Appears to be a CSRF attempt", http.StatusUnauthorized) - } - } - } - - // Attempt to parse token out of the query string - if len(token) == 0 { - token = r.URL.Query().Get("access_token") - isTokenFromQueryString = true - } - - if len(token) == 0 { - return nil, model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token, http.StatusUnauthorized) - } - - session, err := api.app.GetSession(token) - - if err != nil { - return nil, model.NewAppError("ServeHTTP", "api.context.session_expired.app_error", nil, "token="+token, http.StatusUnauthorized) - } else if !session.IsOAuth && isTokenFromQueryString { - return nil, model.NewAppError("ServeHTTP", "api.context.token_provided.app_error", nil, "token="+token, http.StatusUnauthorized) - } - - return session, nil -} - -func (api *BuiltInPluginAPI) I18n(id string, r *http.Request) string { - if r != nil { - f, _ := utils.GetTranslationsAndLocale(nil, r) - return f(id) - } - f, _ := utils.GetTranslationsBySystemLocale() - return f(id) +func (api *PluginAPI) KVDelete(key string) *model.AppError { + return api.app.DeletePluginKey(api.id, key) } -- cgit v1.2.3-1-g7c22 From d7976549a0b45a42c04ac043a15677b7ca1228e9 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Wed, 27 Jun 2018 08:46:38 -0400 Subject: MM-9674 Add plugin API for publishing custom WebSocket events (#8999) * Add plugin API for publishing custom WebSocket events * Add clearer payload comment * Update comment --- app/plugin_api.go | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index ffb8cccd6..fc786202e 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -5,6 +5,7 @@ package app import ( "encoding/json" + "fmt" "github.com/mattermost/mattermost-server/model" ) @@ -176,3 +177,11 @@ func (api *PluginAPI) KVGet(key string) ([]byte, *model.AppError) { func (api *PluginAPI) KVDelete(key string) *model.AppError { return api.app.DeletePluginKey(api.id, key) } + +func (api *PluginAPI) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *model.WebsocketBroadcast) { + api.app.Publish(&model.WebSocketEvent{ + Event: fmt.Sprintf("custom_%v_%v", api.id, event), + Data: payload, + Broadcast: broadcast, + }) +} -- cgit v1.2.3-1-g7c22 From 83a3ac089cff0d05559e6ba5c2c60b09f5cae176 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 3 Jul 2018 09:58:28 -0700 Subject: MM-11029 Adding plugin logging functionality. (#9034) * Capturing stdout, stderr of plugins in logs. * Cleanup go-plugin debug logs. * Adding logging to plugin API * Generating mocks. * godoc convention --- app/plugin_api.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index fc786202e..714ffa700 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -7,18 +7,21 @@ import ( "encoding/json" "fmt" + "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" ) type PluginAPI struct { - id string - app *App + id string + app *App + logger *mlog.SugarLogger } func NewPluginAPI(a *App, manifest *model.Manifest) *PluginAPI { return &PluginAPI{ - id: manifest.Id, - app: a, + id: manifest.Id, + app: a, + logger: a.Log.With(mlog.String("plugin_id", manifest.Id)).Sugar(), } } @@ -185,3 +188,16 @@ func (api *PluginAPI) PublishWebSocketEvent(event string, payload map[string]int Broadcast: broadcast, }) } + +func (api *PluginAPI) LogDebug(msg string, keyValuePairs ...interface{}) { + api.logger.Debug(msg, keyValuePairs...) +} +func (api *PluginAPI) LogInfo(msg string, keyValuePairs ...interface{}) { + api.logger.Info(msg, keyValuePairs...) +} +func (api *PluginAPI) LogError(msg string, keyValuePairs ...interface{}) { + api.logger.Error(msg, keyValuePairs...) +} +func (api *PluginAPI) LogWarn(msg string, keyValuePairs ...interface{}) { + api.logger.Warn(msg, keyValuePairs...) +} -- cgit v1.2.3-1-g7c22 From 359f12db33d45b6ffade0872ddf3652a5c52f4a8 Mon Sep 17 00:00:00 2001 From: Daniel Schalla Date: Sat, 7 Jul 2018 00:32:55 +0200 Subject: First batch of new plugin api methods (#9022) update api mocks Generated new hooks ChannelHasJoinedChannel Implementation User Left Team/Channel Hook; User Joined Team Hook Implementation Update RPC Client and Mocks gofmt go tests fix Add Config API Methods codegne Add Channel Has Been Created Hook Fix ChannelHasBeenCreated hook fix missing context param fix duplicate hooks; remove redudandcy --- app/plugin_api.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index 714ffa700..d76cb83e3 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -42,6 +42,14 @@ func (api *PluginAPI) UnregisterCommand(teamId, trigger string) error { return nil } +func (api *PluginAPI) GetConfig() *model.Config { + return api.app.GetConfig() +} + +func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError { + return api.app.SaveConfig(config, true) +} + func (api *PluginAPI) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { return api.app.CreateTeam(team) } @@ -50,6 +58,10 @@ func (api *PluginAPI) DeleteTeam(teamId string) *model.AppError { return api.app.SoftDeleteTeam(teamId) } +func (api *PluginAPI) GetTeams() ([]*model.Team, *model.AppError) { + return api.app.GetAllTeams() +} + func (api *PluginAPI) GetTeam(teamId string) (*model.Team, *model.AppError) { return api.app.GetTeam(teamId) } @@ -62,6 +74,30 @@ func (api *PluginAPI) UpdateTeam(team *model.Team) (*model.Team, *model.AppError return api.app.UpdateTeam(team) } +func (api *PluginAPI) CreateTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { + return api.app.AddTeamMember(teamId, userId) +} + +func (api *PluginAPI) CreateTeamMembers(teamId string, userIds []string, requestorId string) ([]*model.TeamMember, *model.AppError) { + return api.app.AddTeamMembers(teamId, userIds, requestorId) +} + +func (api *PluginAPI) DeleteTeamMember(teamId, userId, requestorId string) *model.AppError { + return api.app.RemoveUserFromTeam(teamId, userId, requestorId) +} + +func (api *PluginAPI) GetTeamMembers(teamId string, offset, limit int) ([]*model.TeamMember, *model.AppError) { + return api.app.GetTeamMembers(teamId, offset, limit) +} + +func (api *PluginAPI) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) { + return api.app.GetTeamMember(teamId, userId) +} + +func (api *PluginAPI) UpdateTeamMemberRoles(teamId, userId, newRoles string) (*model.TeamMember, *model.AppError) { + return api.app.UpdateTeamMemberRoles(teamId, userId, newRoles) +} + func (api *PluginAPI) CreateUser(user *model.User) (*model.User, *model.AppError) { return api.app.CreateUser(user) } @@ -103,6 +139,10 @@ func (api *PluginAPI) DeleteChannel(channelId string) *model.AppError { return api.app.DeleteChannel(channel, "") } +func (api *PluginAPI) GetPublicChannelsForTeam(teamId string, offset, limit int) (*model.ChannelList, *model.AppError) { + return api.app.GetPublicChannelsForTeam(teamId, offset, limit) +} + func (api *PluginAPI) GetChannel(channelId string) (*model.Channel, *model.AppError) { return api.app.GetChannel(channelId) } @@ -156,6 +196,10 @@ func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError return api.app.CreatePostMissingChannel(post, true) } +func (api *PluginAPI) SendEphemeralPost(userId string, post *model.Post) *model.Post { + return api.app.SendEphemeralPost(userId, post) +} + func (api *PluginAPI) DeletePost(postId string) *model.AppError { _, err := api.app.DeletePost(postId, api.id) return err -- cgit v1.2.3-1-g7c22 From e3c26a0e89253fb626515831d8468050e6235d89 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 9 Jul 2018 07:25:57 -0700 Subject: Adding ability for plugin system to respect the defaults listed in the plugin manifest. (#9066) --- app/plugin_api.go | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index d76cb83e3..279694c44 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -6,30 +6,45 @@ package app import ( "encoding/json" "fmt" + "strings" "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" ) type PluginAPI struct { - id string - app *App - logger *mlog.SugarLogger + id string + app *App + logger *mlog.SugarLogger + manifest *model.Manifest } func NewPluginAPI(a *App, manifest *model.Manifest) *PluginAPI { return &PluginAPI{ - id: manifest.Id, - app: a, - logger: a.Log.With(mlog.String("plugin_id", manifest.Id)).Sugar(), + id: manifest.Id, + manifest: manifest, + app: a, + logger: a.Log.With(mlog.String("plugin_id", manifest.Id)).Sugar(), } } func (api *PluginAPI) LoadPluginConfiguration(dest interface{}) error { - if b, err := json.Marshal(api.app.Config().PluginSettings.Plugins[api.id]); err != nil { + finalConfig := make(map[string]interface{}) + + // First set final config to defaults + for _, setting := range api.manifest.SettingsSchema.Settings { + finalConfig[strings.ToLower(setting.Key)] = setting.Default + } + + // If we have settings given we override the defaults with them + for setting, value := range api.app.Config().PluginSettings.Plugins[api.id] { + finalConfig[strings.ToLower(setting)] = value + } + + if pluginSettingsJsonBytes, err := json.Marshal(finalConfig); err != nil { return err } else { - return json.Unmarshal(b, dest) + return json.Unmarshal(pluginSettingsJsonBytes, dest) } } -- cgit v1.2.3-1-g7c22 From 6daf82073de808a9c7f22fe8f75be815835362cc Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Tue, 10 Jul 2018 10:52:57 -0400 Subject: Don't panic if plugin manifest does not have settings (#9086) --- app/plugin_api.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/plugin_api.go') diff --git a/app/plugin_api.go b/app/plugin_api.go index 279694c44..4130fc4b2 100644 --- a/app/plugin_api.go +++ b/app/plugin_api.go @@ -32,8 +32,10 @@ func (api *PluginAPI) LoadPluginConfiguration(dest interface{}) error { finalConfig := make(map[string]interface{}) // First set final config to defaults - for _, setting := range api.manifest.SettingsSchema.Settings { - finalConfig[strings.ToLower(setting.Key)] = setting.Default + if api.manifest.SettingsSchema != nil { + for _, setting := range api.manifest.SettingsSchema.Settings { + finalConfig[strings.ToLower(setting.Key)] = setting.Default + } } // If we have settings given we override the defaults with them -- cgit v1.2.3-1-g7c22