mirror of https://github.com/portainer/portainer
fix(edgestacks): add a missing webhook uniqueness check BE-12219 (#1251)
parent
6ea16c0060
commit
732337615e
|
@ -73,6 +73,14 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
|
||||||
return httperror.InternalServerError(msg, errors.New(msg))
|
return httperror.InternalServerError(msg, errors.New(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if payload.AutoUpdate != nil && payload.AutoUpdate.Webhook != "" &&
|
||||||
|
(stack.AutoUpdate == nil ||
|
||||||
|
(stack.AutoUpdate != nil && stack.AutoUpdate.Webhook != payload.AutoUpdate.Webhook)) {
|
||||||
|
if isUnique, err := handler.checkUniqueWebhookID(payload.AutoUpdate.Webhook); !isUnique || err != nil {
|
||||||
|
return httperror.Conflict("Webhook ID already exists", errors.New("webhook ID already exists"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
||||||
// The EndpointID property is not available for these stacks, this API environment(endpoint)
|
// The EndpointID property is not available for these stacks, this API environment(endpoint)
|
||||||
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package stacks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
portainer "github.com/portainer/portainer/api"
|
||||||
|
"github.com/portainer/portainer/api/datastore"
|
||||||
|
gittypes "github.com/portainer/portainer/api/git/types"
|
||||||
|
"github.com/portainer/portainer/api/http/security"
|
||||||
|
"github.com/portainer/portainer/api/internal/testhelpers"
|
||||||
|
|
||||||
|
"github.com/gofrs/uuid"
|
||||||
|
"github.com/segmentio/encoding/json"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStackUpdateGitWebhookUniqueness(t *testing.T) {
|
||||||
|
webhook, err := uuid.NewV4()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, store := datastore.MustNewTestStore(t, false, false)
|
||||||
|
|
||||||
|
endpoint := &portainer.Endpoint{
|
||||||
|
ID: 123,
|
||||||
|
Name: "endpoint1",
|
||||||
|
Type: portainer.DockerEnvironment,
|
||||||
|
}
|
||||||
|
err = store.Endpoint().Create(endpoint)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
stack1 := portainer.Stack{
|
||||||
|
ID: 456,
|
||||||
|
EndpointID: endpoint.ID,
|
||||||
|
AutoUpdate: &portainer.AutoUpdateSettings{
|
||||||
|
Webhook: webhook.String(),
|
||||||
|
},
|
||||||
|
GitConfig: &gittypes.RepoConfig{
|
||||||
|
URL: "https://github.com/portainer/portainer.git",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.Stack().Create(&stack1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
stack2 := stack1
|
||||||
|
stack2.ID++
|
||||||
|
stack2.AutoUpdate = nil
|
||||||
|
|
||||||
|
err = store.Stack().Create(&stack2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
handler := NewHandler(testhelpers.NewTestRequestBouncer())
|
||||||
|
handler.DataStore = store
|
||||||
|
|
||||||
|
payload := &stackGitUpdatePayload{
|
||||||
|
AutoUpdate: &portainer.AutoUpdateSettings{
|
||||||
|
Webhook: webhook.String(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonPayload, err := json.Marshal(payload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
url := "/stacks/" + strconv.Itoa(int(stack2.ID)) + "/git?endpointId=" + strconv.Itoa(int(endpoint.ID))
|
||||||
|
req := httptest.NewRequest(http.MethodPost, url, bytes.NewReader(jsonPayload))
|
||||||
|
|
||||||
|
rrc := &security.RestrictedRequestContext{}
|
||||||
|
req = req.WithContext(security.StoreRestrictedRequestContext(req, rrc))
|
||||||
|
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
require.Equal(t, http.StatusConflict, rr.Code)
|
||||||
|
}
|
Loading…
Reference in New Issue