diff --git a/cmd/harbor/root/webhook/create.go b/cmd/harbor/root/webhook/create.go index 5a7371aa8..6081a8a50 100644 --- a/cmd/harbor/root/webhook/create.go +++ b/cmd/harbor/root/webhook/create.go @@ -69,10 +69,12 @@ or leave them out and be guided through an interactive prompt to input each fiel opts.NotifyType != "" && len(opts.EventType) != 0 && opts.EndpointURL != "" { - err = utils.ValidateURL(opts.EndpointURL) + formattedURL := utils.FormatUrl(opts.EndpointURL) + err = utils.ValidateURL(formattedURL) if err != nil { return err } + opts.EndpointURL = formattedURL err = api.CreateWebhook(&opts) } else { err = createWebhookView(createView) diff --git a/cmd/harbor/root/webhook/edit.go b/cmd/harbor/root/webhook/edit.go index 4ba716006..2dedd164f 100644 --- a/cmd/harbor/root/webhook/edit.go +++ b/cmd/harbor/root/webhook/edit.go @@ -85,9 +85,11 @@ or leave them out and use the interactive prompt to select and update a webhook. opts.NotifyType != "" && len(opts.EventType) != 0 && opts.EndpointURL != "" { - if err := utils.ValidateURL(opts.EndpointURL); err != nil { + formattedURL := utils.FormatUrl(opts.EndpointURL) + if err := utils.ValidateURL(formattedURL); err != nil { return err } + opts.EndpointURL = formattedURL err = api.UpdateWebhook(&opts) } else { err = editWebhookView(editView) diff --git a/cmd/harbor/root/webhook/webhook_test.go b/cmd/harbor/root/webhook/webhook_test.go new file mode 100644 index 000000000..8e6d7de95 --- /dev/null +++ b/cmd/harbor/root/webhook/webhook_test.go @@ -0,0 +1,82 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package webhook + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateWebhookCmd_NormalizesEndpointURLBeforeValidation(t *testing.T) { + cmd := CreateWebhookCmd() + + var buf bytes.Buffer + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{ + "my-webhook", + "--project", "my-project", + "--notify-type", "http", + "--event-type", "PUSH_ARTIFACT", + "--endpoint-url", "example.com/webhook", + }) + + err := cmd.Execute() + assert.Error(t, err) + assert.Contains(t, err.Error(), "failed to create webhook") + assert.NotContains(t, err.Error(), "invalid URL format") + assert.NotContains(t, err.Error(), "invalid host") +} + +func TestEditWebhookCmd_NormalizesEndpointURLBeforeValidation(t *testing.T) { + cmd := EditWebhookCmd() + + var buf bytes.Buffer + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{ + "--project", "my-project", + "--webhook-id", "1", + "--notify-type", "http", + "--event-type", "PUSH_ARTIFACT", + "--endpoint-url", "example.com/webhook", + }) + + err := cmd.Execute() + assert.Error(t, err) + assert.Contains(t, err.Error(), "failed to edit webhook") + assert.NotContains(t, err.Error(), "invalid URL format") + assert.NotContains(t, err.Error(), "invalid host") +} + +func TestEditWebhookCmd_InvalidEndpointURLReturnsValidationError(t *testing.T) { + cmd := EditWebhookCmd() + + var buf bytes.Buffer + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{ + "--project", "my-project", + "--webhook-id", "1", + "--notify-type", "http", + "--event-type", "PUSH_ARTIFACT", + "--endpoint-url", "http://", + }) + + err := cmd.Execute() + assert.Error(t, err) + assert.Contains(t, err.Error(), "URL must contain a valid host") +}