MM-17023: Plugin Marketplace (#12183)
* MM-17149 - Extend config.json for marketplace settings (#11933) * MM-17149 - Extend config.json for marketplace settings * Renamed MarketplaceUrl, tracking default marketplace url * Added EnableMarketplace to the client config * Revert "Added EnableMarketplace to the client config" This reverts commit 0f982c4c661c2cd9bb96264e9a01a2363c40d9c5. * MM-17149 - Added EnableMarketplace to the client config (#11958) * Added EnableMarketplace to the client config * Moved EnableMarketplace setting out of limited client configuration * MM-17150, MM-17545, MM-18100 - Implement GET /api/v4/plugins/m… (#11977) * MM-17150 - Implement GET /api/v4/plugins/marketplace proxying upstream MM-17545 - Merge locally installed plugins into GET /api/v4/plugins/marketplace * Replaced MarketplacePluginState with Installed * Setting InstalledVersion instead of Installed * marketplace client setting per_page if non zero * Creating insecure client for marketplace url * Fixed trailing slash for default marketplace url * Adding filtering * Fixed function names * Renamed Manifest() to GetManifest(), added godoc for BaseMarketplacePlugin * Handling plugin.ErrNotFound correctly * Checking err == nil instead when a plugin is installed * MM-18450 - Local-only plugin search (#12152) * MM-17846: plugin icons (#12157) * MM-17846: add support for plugin icons Extend the model definitions to support plugin icons from the marketplace. * s/IconURL/IconData * MM-18475 - Converge on snake_case responses from the marketplace (#12179) * MM-18520 - MM-Server should forward server version to marketplace server (#12181) * Renamed request to filter client4.GetMarketplacePlugins * Renamed request to filter * Guarding against bad marketplace server response
Этот коммит содержится в:
коммит произвёл
Ali Farooq
родитель
86891091c0
Коммит
4ce7b92283
@@ -4519,6 +4519,31 @@ func (c *Client4) DisablePlugin(id string) (bool, *Response) {
|
||||
return CheckStatusOK(r), BuildResponse(r)
|
||||
}
|
||||
|
||||
// GetMarketplacePlugins will return a list of plugins that an admin can install.
|
||||
// WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
|
||||
func (c *Client4) GetMarketplacePlugins(filter *MarketplacePluginFilter) ([]*MarketplacePlugin, *Response) {
|
||||
route := c.GetPluginsRoute() + "/marketplace"
|
||||
u, parseErr := url.Parse(route)
|
||||
if parseErr != nil {
|
||||
return nil, &Response{Error: NewAppError("GetMarketplacePlugins", "model.client.parse_plugins.app_error", nil, parseErr.Error(), http.StatusBadRequest)}
|
||||
}
|
||||
|
||||
filter.ApplyToURL(u)
|
||||
|
||||
r, err := c.DoApiGet(u.String(), "")
|
||||
if err != nil {
|
||||
return nil, BuildErrorResponse(r, err)
|
||||
}
|
||||
defer closeBody(r)
|
||||
|
||||
plugins, readerErr := MarketplacePluginsFromReader(r.Body)
|
||||
if readerErr != nil {
|
||||
return nil, BuildErrorResponse(r, NewAppError(route, "model.client.parse_plugins.app_error", nil, err.Error(), http.StatusBadRequest))
|
||||
}
|
||||
|
||||
return plugins, BuildResponse(r)
|
||||
}
|
||||
|
||||
// UpdateChannelScheme will update a channel's scheme.
|
||||
func (c *Client4) UpdateChannelScheme(channelId, schemeId string) (bool, *Response) {
|
||||
sip := &SchemeIDPatch{SchemeID: &schemeId}
|
||||
|
||||
@@ -171,8 +171,10 @@ const (
|
||||
DATA_RETENTION_SETTINGS_DEFAULT_FILE_RETENTION_DAYS = 365
|
||||
DATA_RETENTION_SETTINGS_DEFAULT_DELETION_JOB_START_TIME = "02:00"
|
||||
|
||||
PLUGIN_SETTINGS_DEFAULT_DIRECTORY = "./plugins"
|
||||
PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY = "./client/plugins"
|
||||
PLUGIN_SETTINGS_DEFAULT_DIRECTORY = "./plugins"
|
||||
PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY = "./client/plugins"
|
||||
PLUGIN_SETTINGS_DEFAULT_ENABLE_MARKETPLACE = true
|
||||
PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL = "https://marketplace.integrations.mattermost.com"
|
||||
|
||||
COMPLIANCE_EXPORT_TYPE_CSV = "csv"
|
||||
COMPLIANCE_EXPORT_TYPE_ACTIANCE = "actiance"
|
||||
@@ -2201,6 +2203,8 @@ type PluginSettings struct {
|
||||
ClientDirectory *string `restricted:"true"`
|
||||
Plugins map[string]map[string]interface{}
|
||||
PluginStates map[string]*PluginState
|
||||
EnableMarketplace *bool
|
||||
MarketplaceUrl *string
|
||||
}
|
||||
|
||||
func (s *PluginSettings) SetDefaults(ls LogSettings) {
|
||||
@@ -2220,22 +2224,14 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) {
|
||||
s.EnableHealthCheck = NewBool(true)
|
||||
}
|
||||
|
||||
if s.Directory == nil {
|
||||
if s.Directory == nil || *s.Directory == "" {
|
||||
s.Directory = NewString(PLUGIN_SETTINGS_DEFAULT_DIRECTORY)
|
||||
}
|
||||
|
||||
if *s.Directory == "" {
|
||||
*s.Directory = PLUGIN_SETTINGS_DEFAULT_DIRECTORY
|
||||
}
|
||||
|
||||
if s.ClientDirectory == nil {
|
||||
if s.ClientDirectory == nil || *s.ClientDirectory == "" {
|
||||
s.ClientDirectory = NewString(PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY)
|
||||
}
|
||||
|
||||
if *s.ClientDirectory == "" {
|
||||
*s.ClientDirectory = PLUGIN_SETTINGS_DEFAULT_CLIENT_DIRECTORY
|
||||
}
|
||||
|
||||
if s.Plugins == nil {
|
||||
s.Plugins = make(map[string]map[string]interface{})
|
||||
}
|
||||
@@ -2248,6 +2244,14 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) {
|
||||
// Enable the NPS plugin by default if diagnostics are enabled
|
||||
s.PluginStates["com.mattermost.nps"] = &PluginState{Enable: ls.EnableDiagnostics == nil || *ls.EnableDiagnostics}
|
||||
}
|
||||
|
||||
if s.EnableMarketplace == nil {
|
||||
s.EnableMarketplace = NewBool(PLUGIN_SETTINGS_DEFAULT_ENABLE_MARKETPLACE)
|
||||
}
|
||||
|
||||
if s.MarketplaceUrl == nil || *s.MarketplaceUrl == "" {
|
||||
s.MarketplaceUrl = NewString(PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL)
|
||||
}
|
||||
}
|
||||
|
||||
type GlobalRelayMessageExportSettings struct {
|
||||
|
||||
69
model/marketplace_plugin.go
Обычный файл
69
model/marketplace_plugin.go
Обычный файл
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// BaseMarketplacePlugin is a Mattermost plugin received from the marketplace server.
|
||||
type BaseMarketplacePlugin struct {
|
||||
HomepageURL string `json:"homepage_url"`
|
||||
DownloadURL string `json:"download_url"`
|
||||
IconData string `json:"icon_data"`
|
||||
Manifest *Manifest `json:"manifest"`
|
||||
}
|
||||
|
||||
// MarketplacePlugin is a state aware marketplace plugin.
|
||||
type MarketplacePlugin struct {
|
||||
*BaseMarketplacePlugin
|
||||
InstalledVersion string `json:"installed_version"`
|
||||
}
|
||||
|
||||
// BaseMarketplacePluginsFromReader decodes a json-encoded list of plugins from the given io.Reader.
|
||||
func BaseMarketplacePluginsFromReader(reader io.Reader) ([]*BaseMarketplacePlugin, error) {
|
||||
plugins := []*BaseMarketplacePlugin{}
|
||||
decoder := json.NewDecoder(reader)
|
||||
|
||||
if err := decoder.Decode(&plugins); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// MarketplacePluginsFromReader decodes a json-encoded list of plugins from the given io.Reader.
|
||||
func MarketplacePluginsFromReader(reader io.Reader) ([]*MarketplacePlugin, error) {
|
||||
plugins := []*MarketplacePlugin{}
|
||||
decoder := json.NewDecoder(reader)
|
||||
|
||||
if err := decoder.Decode(&plugins); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// MarketplacePluginFilter describes the parameters to request a list of plugins.
|
||||
type MarketplacePluginFilter struct {
|
||||
Page int
|
||||
PerPage int
|
||||
Filter string
|
||||
ServerVersion string
|
||||
}
|
||||
|
||||
// ApplyToURL modifies the given url to include query string parameters for the request.
|
||||
func (filter *MarketplacePluginFilter) ApplyToURL(u *url.URL) {
|
||||
q := u.Query()
|
||||
q.Add("page", strconv.Itoa(filter.Page))
|
||||
if filter.PerPage > 0 {
|
||||
q.Add("per_page", strconv.Itoa(filter.PerPage))
|
||||
}
|
||||
q.Add("filter", filter.Filter)
|
||||
q.Add("server_version", filter.ServerVersion)
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
Ссылка в новой задаче
Block a user