Skip to content

Commit be48397

Browse files
adelowotechknowlogick
authored andcommitted
Slack webhook channel name cannot be empty or just contain an hashtag (#4786)
1 parent 6e03390 commit be48397

File tree

6 files changed

+69
-5
lines changed

6 files changed

+69
-5
lines changed

modules/auth/repo_form.go

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"strings"
1111

1212
"code.gitea.io/gitea/models"
13+
"code.gitea.io/gitea/routers/utils"
14+
1315
"github.com/Unknwon/com"
1416
"github.com/go-macaron/binding"
1517
"gopkg.in/macaron.v1"
@@ -225,6 +227,11 @@ func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs binding.Errors) b
225227
return validate(errs, ctx.Data, f, ctx.Locale)
226228
}
227229

230+
// HasInvalidChannel validates the channel name is in the right format
231+
func (f NewSlackHookForm) HasInvalidChannel() bool {
232+
return !utils.IsValidSlackChannel(f.Channel)
233+
}
234+
228235
// NewDiscordHookForm form for creating discord hook
229236
type NewDiscordHookForm struct {
230237
PayloadURL string `binding:"Required;ValidUrl"`

options/locale/locale_en-US.ini

+1
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ settings.search_user_placeholder = Search user…
10441044
settings.org_not_allowed_to_be_collaborator = Organizations cannot be added as a collaborator.
10451045
settings.user_is_org_member = The user is an organization member who cannot be added as a collaborator.
10461046
settings.add_webhook = Add Webhook
1047+
settings.add_webhook.invalid_channel_name = Webhook channel name cannot be empty and cannot contain only a # character.
10471048
settings.hooks_desc = Webhooks automatically make HTTP POST requests to a server when certain Gitea events trigger. Read more in the <a target="_blank" rel="noopener noreferrer" href="%s">webhooks guide</a>.
10481049
settings.webhook_deletion = Remove Webhook
10491050
settings.webhook_deletion_desc = Removing a webhook deletes its settings and delivery history. Continue?

routers/api/v1/utils/hook.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
package utils
66

77
import (
8-
api "code.gitea.io/sdk/gitea"
9-
108
"encoding/json"
119
"net/http"
10+
"strings"
1211

1312
"code.gitea.io/gitea/models"
1413
"code.gitea.io/gitea/modules/context"
1514
"code.gitea.io/gitea/routers/api/v1/convert"
15+
"code.gitea.io/gitea/routers/utils"
16+
api "code.gitea.io/sdk/gitea"
17+
1618
"github.com/Unknwon/com"
1719
)
1820

@@ -119,8 +121,14 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
119121
ctx.Error(422, "", "Missing config option: channel")
120122
return nil, false
121123
}
124+
125+
if !utils.IsValidSlackChannel(channel) {
126+
ctx.Error(400, "", "Invalid slack channel name")
127+
return nil, false
128+
}
129+
122130
meta, err := json.Marshal(&models.SlackMeta{
123-
Channel: channel,
131+
Channel: strings.TrimSpace(channel),
124132
Username: form.Config["username"],
125133
IconURL: form.Config["icon_url"],
126134
Color: form.Config["color"],

routers/repo/webhook.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,14 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
332332
return
333333
}
334334

335+
if form.HasInvalidChannel() {
336+
ctx.Flash.Error(ctx.Tr("repo.settings.add_webhook.invalid_channel_name"))
337+
ctx.Redirect(orCtx.Link + "/settings/hooks/slack/new")
338+
return
339+
}
340+
335341
meta, err := json.Marshal(&models.SlackMeta{
336-
Channel: form.Channel,
342+
Channel: strings.TrimSpace(form.Channel),
337343
Username: form.Username,
338344
IconURL: form.IconURL,
339345
Color: form.Color,
@@ -515,8 +521,14 @@ func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) {
515521
return
516522
}
517523

524+
if form.HasInvalidChannel() {
525+
ctx.Flash.Error(ctx.Tr("repo.settings.add_webhook.invalid_channel_name"))
526+
ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
527+
return
528+
}
529+
518530
meta, err := json.Marshal(&models.SlackMeta{
519-
Channel: form.Channel,
531+
Channel: strings.TrimSpace(form.Channel),
520532
Username: form.Username,
521533
IconURL: form.IconURL,
522534
Color: form.Color,

routers/utils/utils.go

+19
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,22 @@ func RemoveUsernameParameterSuffix(name string) string {
1515
}
1616
return name
1717
}
18+
19+
// IsValidSlackChannel validates a channel name conforms to what slack expects.
20+
// It makes sure a channel name cannot be empty and invalid ( only an # )
21+
func IsValidSlackChannel(channelName string) bool {
22+
switch len(strings.TrimSpace(channelName)) {
23+
case 0:
24+
return false
25+
case 1:
26+
// Keep default behaviour where a channel name is still
27+
// valid without an #
28+
// But if it contains only an #, it should be regarded as
29+
// invalid
30+
if channelName[0] == '#' {
31+
return false
32+
}
33+
}
34+
35+
return true
36+
}

routers/utils/utils_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,20 @@ func TestRemoveUsernameParameterSuffix(t *testing.T) {
1515
assert.Equal(t, "foobar", RemoveUsernameParameterSuffix("foobar"))
1616
assert.Equal(t, "", RemoveUsernameParameterSuffix(""))
1717
}
18+
19+
func TestIsValidSlackChannel(t *testing.T) {
20+
tt := []struct {
21+
channelName string
22+
expected bool
23+
}{
24+
{"gitea", true},
25+
{" ", false},
26+
{"#", false},
27+
{"gitea ", true},
28+
{" gitea", true},
29+
}
30+
31+
for _, v := range tt {
32+
assert.Equal(t, v.expected, IsValidSlackChannel(v.channelName))
33+
}
34+
}

0 commit comments

Comments
 (0)