[MM-41290] Add Endpoint to complete onboarding (#19435)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
a733fb840d
Коммит
321b19e3db
@@ -1472,8 +1472,7 @@ func TestInstallMarketplacePlugin(t *testing.T) {
|
|||||||
*cfg.PluginSettings.MarketplaceURL = testServer.URL
|
*cfg.PluginSettings.MarketplaceURL = testServer.URL
|
||||||
})
|
})
|
||||||
|
|
||||||
// The content of the request is irrelevant. This test only cares about enterprise_plugins.
|
pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
|
||||||
pRequest := &model.InstallMarketplacePluginRequest{}
|
|
||||||
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
CheckInternalErrorStatus(t, resp)
|
CheckInternalErrorStatus(t, resp)
|
||||||
@@ -1511,8 +1510,7 @@ func TestInstallMarketplacePlugin(t *testing.T) {
|
|||||||
*l.Features.EnterprisePlugins = false
|
*l.Features.EnterprisePlugins = false
|
||||||
th.App.Srv().SetLicense(l)
|
th.App.Srv().SetLicense(l)
|
||||||
|
|
||||||
// The content of the request is irrelevant. This test only cares about enterprise_plugins.
|
pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
|
||||||
pRequest := &model.InstallMarketplacePluginRequest{}
|
|
||||||
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
CheckInternalErrorStatus(t, resp)
|
CheckInternalErrorStatus(t, resp)
|
||||||
@@ -1546,8 +1544,7 @@ func TestInstallMarketplacePlugin(t *testing.T) {
|
|||||||
|
|
||||||
th.App.Srv().SetLicense(model.NewTestLicense("enterprise_plugins"))
|
th.App.Srv().SetLicense(model.NewTestLicense("enterprise_plugins"))
|
||||||
|
|
||||||
// The content of the request is irrelevant. This test only cares about enterprise_plugins.
|
pRequest := &model.InstallMarketplacePluginRequest{Id: "testplugin"}
|
||||||
pRequest := &model.InstallMarketplacePluginRequest{}
|
|
||||||
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
manifest, resp, err := client.InstallMarketplacePlugin(pRequest)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
CheckInternalErrorStatus(t, resp)
|
CheckInternalErrorStatus(t, resp)
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ func (api *API) InitSystem() {
|
|||||||
api.BaseRoutes.APIRoot.Handle("/warn_metrics/trial-license-ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.APIHandler(requestTrialLicenseAndAckWarnMetric)).Methods("POST")
|
api.BaseRoutes.APIRoot.Handle("/warn_metrics/trial-license-ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.APIHandler(requestTrialLicenseAndAckWarnMetric)).Methods("POST")
|
||||||
api.BaseRoutes.System.Handle("/notices/{team_id:[A-Za-z0-9]+}", api.APISessionRequired(getProductNotices)).Methods("GET")
|
api.BaseRoutes.System.Handle("/notices/{team_id:[A-Za-z0-9]+}", api.APISessionRequired(getProductNotices)).Methods("GET")
|
||||||
api.BaseRoutes.System.Handle("/notices/view", api.APISessionRequired(updateViewedProductNotices)).Methods("PUT")
|
api.BaseRoutes.System.Handle("/notices/view", api.APISessionRequired(updateViewedProductNotices)).Methods("PUT")
|
||||||
|
|
||||||
api.BaseRoutes.System.Handle("/support_packet", api.APISessionRequired(generateSupportPacket)).Methods("GET")
|
api.BaseRoutes.System.Handle("/support_packet", api.APISessionRequired(generateSupportPacket)).Methods("GET")
|
||||||
|
api.BaseRoutes.System.Handle("/onboarding/complete", api.APIHandler(completeOnboarding)).Methods("POST")
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSupportPacket(c *Context, w http.ResponseWriter, r *http.Request) {
|
func generateSupportPacket(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -880,3 +880,29 @@ func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Reque
|
|||||||
auditRec.Success()
|
auditRec.Success()
|
||||||
ReturnStatusOK(w)
|
ReturnStatusOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
|
||||||
|
c.Err = model.NewAppError("completeOnboarding", "app.system.complete_onboarding_request.no_first_user", nil, "", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
auditRec := c.MakeAuditRecord("completeOnboarding", audit.Fail)
|
||||||
|
defer c.LogAuditRec(auditRec)
|
||||||
|
|
||||||
|
onboardingRequest, err := model.CompleteOnboardingRequestFromReader(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = model.NewAppError("completeOnboarding", "app.system.complete_onboarding_request.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
auditRec.AddMeta("install_plugin", onboardingRequest.InstallPlugins)
|
||||||
|
|
||||||
|
appErr := c.App.CompleteOnboarding(onboardingRequest)
|
||||||
|
if appErr != nil {
|
||||||
|
c.Err = appErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
auditRec.Success()
|
||||||
|
ReturnStatusOK(w)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ package api4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -20,6 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mattermost/mattermost-server/v6/model"
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/utils/fileutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetPing(t *testing.T) {
|
func TestGetPing(t *testing.T) {
|
||||||
@@ -778,3 +782,103 @@ func TestPushNotificationAck(t *testing.T) {
|
|||||||
assert.NotNil(t, resp.Body)
|
assert.NotNil(t, resp.Body)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompleteOnboarding(t *testing.T) {
|
||||||
|
th := Setup(t)
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
path, _ := fileutils.FindDir("tests")
|
||||||
|
signatureFilename := "testplugin2.tar.gz.sig"
|
||||||
|
signatureFileReader, err := os.Open(filepath.Join(path, signatureFilename))
|
||||||
|
require.NoError(t, err)
|
||||||
|
sigFile, err := ioutil.ReadAll(signatureFileReader)
|
||||||
|
require.NoError(t, err)
|
||||||
|
pluginSignature := base64.StdEncoding.EncodeToString(sigFile)
|
||||||
|
|
||||||
|
tarData, err := ioutil.ReadFile(filepath.Join(path, "testplugin2.tar.gz"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
pluginServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
res.WriteHeader(http.StatusOK)
|
||||||
|
res.Write(tarData)
|
||||||
|
}))
|
||||||
|
defer pluginServer.Close()
|
||||||
|
|
||||||
|
samplePlugins := []*model.MarketplacePlugin{{
|
||||||
|
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
|
||||||
|
HomepageURL: "https://example.com/mattermost/mattermost-plugin-nps",
|
||||||
|
IconData: "https://example.com/icon.svg",
|
||||||
|
DownloadURL: pluginServer.URL,
|
||||||
|
Manifest: &model.Manifest{
|
||||||
|
Id: "testplugin2",
|
||||||
|
Name: "testplugin2",
|
||||||
|
Description: "a second plugin",
|
||||||
|
Version: "1.2.3",
|
||||||
|
MinServerVersion: "",
|
||||||
|
},
|
||||||
|
Signature: pluginSignature,
|
||||||
|
},
|
||||||
|
InstalledVersion: "",
|
||||||
|
}}
|
||||||
|
|
||||||
|
marketplaceServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
res.WriteHeader(http.StatusOK)
|
||||||
|
var data []byte
|
||||||
|
data, err = json.Marshal(samplePlugins)
|
||||||
|
require.NoError(t, err)
|
||||||
|
res.Write(data)
|
||||||
|
}))
|
||||||
|
defer marketplaceServer.Close()
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
*cfg.PluginSettings.Enable = true
|
||||||
|
*cfg.PluginSettings.EnableMarketplace = false
|
||||||
|
*cfg.PluginSettings.EnableRemoteMarketplace = true
|
||||||
|
*cfg.PluginSettings.MarketplaceURL = marketplaceServer.URL
|
||||||
|
*cfg.PluginSettings.AllowInsecureDownloadURL = true
|
||||||
|
})
|
||||||
|
|
||||||
|
key, err := os.Open(filepath.Join(path, "development-private-key.asc"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
appErr := th.App.AddPublicKey("pub_key", key)
|
||||||
|
require.Nil(t, appErr)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
appErr = th.App.DeletePublicKey("pub_key")
|
||||||
|
require.Nil(t, appErr)
|
||||||
|
})
|
||||||
|
|
||||||
|
req := &model.CompleteOnboardingRequest{
|
||||||
|
InstallPlugins: []string{"testplugin2"},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("as a regular user", func(t *testing.T) {
|
||||||
|
resp, err := th.Client.CompleteOnboarding(req)
|
||||||
|
require.Error(t, err)
|
||||||
|
CheckForbiddenStatus(t, resp)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("as a system admin", func(t *testing.T) {
|
||||||
|
resp, err := th.SystemAdminClient.CompleteOnboarding(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
resp, err = th.SystemAdminClient.RemovePlugin("testplugin2")
|
||||||
|
require.NoError(t, err)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
})
|
||||||
|
|
||||||
|
installedPlugins, resp, err := th.SystemAdminClient.GetPlugins()
|
||||||
|
require.NoError(t, err)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, p := range installedPlugins.Active {
|
||||||
|
if p.Id == "testplugin2" {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.True(t, found, "testplugin2 should have been installed and enabled")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -438,6 +438,7 @@ type AppIface interface {
|
|||||||
CompareAndDeletePluginKey(pluginID string, key string, oldValue []byte) (bool, *model.AppError)
|
CompareAndDeletePluginKey(pluginID string, key string, oldValue []byte) (bool, *model.AppError)
|
||||||
CompareAndSetPluginKey(pluginID string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
CompareAndSetPluginKey(pluginID string, key string, oldValue, newValue []byte) (bool, *model.AppError)
|
||||||
CompleteOAuth(c *request.Context, service string, body io.ReadCloser, teamID string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError)
|
CompleteOAuth(c *request.Context, service string, body io.ReadCloser, teamID string, props map[string]string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
|
CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError
|
||||||
CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError)
|
CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError)
|
||||||
Compliance() einterfaces.ComplianceInterface
|
Compliance() einterfaces.ComplianceInterface
|
||||||
Config() *model.Config
|
Config() *model.Config
|
||||||
|
|||||||
46
app/onboarding.go
Обычный файл
46
app/onboarding.go
Обычный файл
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
if !*a.Config().PluginSettings.Enable {
|
||||||
|
return model.NewAppError("completeOnboarding", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range request.InstallPlugins {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func(id string) {
|
||||||
|
defer wg.Done()
|
||||||
|
installRequest := &model.InstallMarketplacePluginRequest{
|
||||||
|
Id: id,
|
||||||
|
}
|
||||||
|
_, appErr := a.Channels().InstallMarketplacePlugin(installRequest)
|
||||||
|
if appErr != nil {
|
||||||
|
mlog.Error("Failed to install plugin for onboarding", mlog.String("id", id), mlog.Err(appErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
appErr = a.Channels().enablePlugin(id)
|
||||||
|
if appErr != nil {
|
||||||
|
mlog.Error("Failed to enable plugin for onboarding", mlog.String("id", id), mlog.Err(appErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1671,6 +1671,28 @@ func (a *OpenTracingAppLayer) CompleteOAuth(c *request.Context, service string,
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) CompleteOnboarding(request *model.CompleteOnboardingRequest) *model.AppError {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteOnboarding")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store.SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0 := a.app.CompleteOnboarding(request)
|
||||||
|
|
||||||
|
if resultVar0 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError) {
|
func (a *OpenTracingAppLayer) CompleteSwitchWithOAuth(service string, userData io.Reader, email string, tokenUser *model.User) (*model.User, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteSwitchWithOAuth")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CompleteSwitchWithOAuth")
|
||||||
|
|||||||
@@ -538,6 +538,8 @@ func (a *App) GetMarketplacePlugins(filter *model.MarketplacePluginFilter) ([]*m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getPrepackagedPlugin returns a pre-packaged plugin.
|
// getPrepackagedPlugin returns a pre-packaged plugin.
|
||||||
|
//
|
||||||
|
// If version is empty, the first matching plugin is returned.
|
||||||
func (ch *Channels) getPrepackagedPlugin(pluginID, version string) (*plugin.PrepackagedPlugin, *model.AppError) {
|
func (ch *Channels) getPrepackagedPlugin(pluginID, version string) (*plugin.PrepackagedPlugin, *model.AppError) {
|
||||||
pluginsEnvironment := ch.GetPluginsEnvironment()
|
pluginsEnvironment := ch.GetPluginsEnvironment()
|
||||||
if pluginsEnvironment == nil {
|
if pluginsEnvironment == nil {
|
||||||
@@ -546,7 +548,7 @@ func (ch *Channels) getPrepackagedPlugin(pluginID, version string) (*plugin.Prep
|
|||||||
|
|
||||||
prepackagedPlugins := pluginsEnvironment.PrepackagedPlugins()
|
prepackagedPlugins := pluginsEnvironment.PrepackagedPlugins()
|
||||||
for _, p := range prepackagedPlugins {
|
for _, p := range prepackagedPlugins {
|
||||||
if p.Manifest.Id == pluginID && p.Manifest.Version == version {
|
if p.Manifest.Id == pluginID && (version == "" || p.Manifest.Version == version) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -555,6 +557,8 @@ func (ch *Channels) getPrepackagedPlugin(pluginID, version string) (*plugin.Prep
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getRemoteMarketplacePlugin returns plugin from marketplace-server.
|
// getRemoteMarketplacePlugin returns plugin from marketplace-server.
|
||||||
|
//
|
||||||
|
// If version is empty, the latest compatible version is used.
|
||||||
func (ch *Channels) getRemoteMarketplacePlugin(pluginID, version string) (*model.BaseMarketplacePlugin, *model.AppError) {
|
func (ch *Channels) getRemoteMarketplacePlugin(pluginID, version string) (*model.BaseMarketplacePlugin, *model.AppError) {
|
||||||
marketplaceClient, err := marketplace.NewClient(
|
marketplaceClient, err := marketplace.NewClient(
|
||||||
*ch.srv.Config().PluginSettings.MarketplaceURL,
|
*ch.srv.Config().PluginSettings.MarketplaceURL,
|
||||||
@@ -566,9 +570,13 @@ func (ch *Channels) getRemoteMarketplacePlugin(pluginID, version string) (*model
|
|||||||
|
|
||||||
filter := ch.getBaseMarketplaceFilter()
|
filter := ch.getBaseMarketplaceFilter()
|
||||||
filter.PluginId = pluginID
|
filter.PluginId = pluginID
|
||||||
filter.ReturnAllVersions = true
|
|
||||||
|
|
||||||
plugin, err := marketplaceClient.GetPlugin(filter, version)
|
var plugin *model.BaseMarketplacePlugin
|
||||||
|
if version != "" {
|
||||||
|
plugin, err = marketplaceClient.GetPlugin(filter, version)
|
||||||
|
} else {
|
||||||
|
plugin, err = marketplaceClient.GetLatestPlugin(filter)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("GetMarketplacePlugin", "app.plugin.marketplace_plugins.not_found.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("GetMarketplacePlugin", "app.plugin.marketplace_plugins.not_found.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6075,6 +6075,14 @@
|
|||||||
"id": "app.submit_interactive_dialog.json_error",
|
"id": "app.submit_interactive_dialog.json_error",
|
||||||
"translation": "Encountered an error encoding JSON for the interactive dialog."
|
"translation": "Encountered an error encoding JSON for the interactive dialog."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.system.complete_onboarding_request.app_error",
|
||||||
|
"translation": "Failed to decode the complete onboarding request."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.system.complete_onboarding_request.no_first_user",
|
||||||
|
"translation": "Onboarding can only be completed by a System Administrator."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.system.get.app_error",
|
"id": "app.system.get.app_error",
|
||||||
"translation": "We encountered an error finding the system properties."
|
"translation": "We encountered an error finding the system properties."
|
||||||
|
|||||||
@@ -7432,6 +7432,20 @@ func (c *Client4) MarkNoticesViewed(ids []string) (*Response, error) {
|
|||||||
return BuildResponse(r), nil
|
return BuildResponse(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client4) CompleteOnboarding(request *CompleteOnboardingRequest) (*Response, error) {
|
||||||
|
buf, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewAppError("CompleteOnboarding", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
r, err := c.DoAPIPost(c.systemRoute()+"/onboarding/complete", string(buf))
|
||||||
|
if err != nil {
|
||||||
|
return BuildResponse(r), err
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
|
return BuildResponse(r), nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateUpload creates a new upload session.
|
// CreateUpload creates a new upload session.
|
||||||
func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response, error) {
|
func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response, error) {
|
||||||
buf, err := json.Marshal(us)
|
buf, err := json.Marshal(us)
|
||||||
|
|||||||
25
model/onboarding.go
Обычный файл
25
model/onboarding.go
Обычный файл
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompleteOnboardingRequest describes parameters of the requested plugin.
|
||||||
|
type CompleteOnboardingRequest struct {
|
||||||
|
InstallPlugins []string `json:"install_plugins"` // InstallPlugins is a list of plugins to be installed
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompleteOnboardingRequest decodes a json-encoded request from the given io.Reader.
|
||||||
|
func CompleteOnboardingRequestFromReader(reader io.Reader) (*CompleteOnboardingRequest, error) {
|
||||||
|
var r *CompleteOnboardingRequest
|
||||||
|
err := json.NewDecoder(reader).Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
@@ -66,6 +66,16 @@ func (c *Client) GetPlugins(request *model.MarketplacePluginFilter) ([]*model.Ba
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetPlugin(filter *model.MarketplacePluginFilter, pluginVersion string) (*model.BaseMarketplacePlugin, error) {
|
func (c *Client) GetPlugin(filter *model.MarketplacePluginFilter, pluginVersion string) (*model.BaseMarketplacePlugin, error) {
|
||||||
|
filter.ReturnAllVersions = true
|
||||||
|
|
||||||
|
if filter.PluginId == "" {
|
||||||
|
return nil, errors.New("missing pluginID")
|
||||||
|
}
|
||||||
|
|
||||||
|
if pluginVersion == "" {
|
||||||
|
return nil, errors.New("missing pluginVersion")
|
||||||
|
}
|
||||||
|
|
||||||
plugins, err := c.GetPlugins(filter)
|
plugins, err := c.GetPlugins(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -78,6 +88,29 @@ func (c *Client) GetPlugin(filter *model.MarketplacePluginFilter, pluginVersion
|
|||||||
return nil, errors.New("plugin not found")
|
return nil, errors.New("plugin not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetLatestPlugin(filter *model.MarketplacePluginFilter) (*model.BaseMarketplacePlugin, error) {
|
||||||
|
filter.ReturnAllVersions = false
|
||||||
|
|
||||||
|
if filter.PluginId == "" {
|
||||||
|
return nil, errors.New("no pluginID provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins, err := c.GetPlugins(filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(plugins) == 0 {
|
||||||
|
return nil, errors.New("plugin not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(plugins) > 1 {
|
||||||
|
return nil, errors.Errorf("unexpectedly more then one plugin was returned from the marketplace")
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
// closeBody ensures the Body of an http.Response is properly closed.
|
// closeBody ensures the Body of an http.Response is properly closed.
|
||||||
func closeBody(r *http.Response) {
|
func closeBody(r *http.Response) {
|
||||||
if r.Body != nil {
|
if r.Body != nil {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user