From 6f00821f3d3aa1eee39af93071d44433c6ff1d66 Mon Sep 17 00:00:00 2001
From: oliverpool <git@olivier.pfad.fr>
Date: Thu, 21 Mar 2024 13:51:35 +0100
Subject: [PATCH] [REFACTOR] webhook slack endpoints

---
 routers/web/repo/setting/webhook.go | 27 -----------------
 routers/web/web.go                  |  2 --
 services/forms/repo_form.go         | 24 ---------------
 services/webhook/slack.go           | 45 ++++++++++++++++++++++++++++-
 4 files changed, 44 insertions(+), 54 deletions(-)

diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go
index 8900942190..ca686cac63 100644
--- a/routers/web/repo/setting/webhook.go
+++ b/routers/web/repo/setting/webhook.go
@@ -481,33 +481,6 @@ func mSTeamsHookParams(ctx *context.Context) webhookParams {
 	}
 }
 
-// SlackHooksNewPost response for creating Slack webhook
-func SlackHooksNewPost(ctx *context.Context) {
-	createWebhook(ctx, slackHookParams(ctx))
-}
-
-// SlackHooksEditPost response for editing Slack webhook
-func SlackHooksEditPost(ctx *context.Context) {
-	editWebhook(ctx, slackHookParams(ctx))
-}
-
-func slackHookParams(ctx *context.Context) webhookParams {
-	form := web.GetForm(ctx).(*forms.NewSlackHookForm)
-
-	return webhookParams{
-		Type:        webhook_module.SLACK,
-		URL:         form.PayloadURL,
-		ContentType: webhook.ContentTypeJSON,
-		WebhookForm: form.WebhookForm,
-		Meta: &webhook_service.SlackMeta{
-			Channel:  strings.TrimSpace(form.Channel),
-			Username: form.Username,
-			IconURL:  form.IconURL,
-			Color:    form.Color,
-		},
-	}
-}
-
 // FeishuHooksNewPost response for creating Feishu webhook
 func FeishuHooksNewPost(ctx *context.Context) {
 	createWebhook(ctx, feishuHookParams(ctx))
diff --git a/routers/web/web.go b/routers/web/web.go
index 06ef485422..92f2680657 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -403,7 +403,6 @@ func registerRoutes(m *web.Route) {
 	addWebhookAddRoutes := func() {
 		m.Get("/{type}/new", repo_setting.WebhooksNew)
 		m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksNewPost)
-		m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksNewPost)
 		m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo_setting.DiscordHooksNewPost)
 		m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo_setting.DingtalkHooksNewPost)
 		m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo_setting.TelegramHooksNewPost)
@@ -416,7 +415,6 @@ func registerRoutes(m *web.Route) {
 
 	addWebhookEditRoutes := func() {
 		m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksEditPost)
-		m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksEditPost)
 		m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo_setting.DiscordHooksEditPost)
 		m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo_setting.DingtalkHooksEditPost)
 		m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo_setting.TelegramHooksEditPost)
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index 5a372ab67c..d251faf225 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -16,7 +16,6 @@ import (
 	"code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/web/middleware"
 	"code.gitea.io/gitea/services/context"
-	"code.gitea.io/gitea/services/webhook"
 
 	"gitea.com/go-chi/binding"
 )
@@ -293,29 +292,6 @@ func (f *NewGogshookForm) Validate(req *http.Request, errs binding.Errors) bindi
 	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
-// NewSlackHookForm form for creating slack hook
-type NewSlackHookForm struct {
-	PayloadURL string `binding:"Required;ValidUrl"`
-	Channel    string `binding:"Required"`
-	Username   string
-	IconURL    string
-	Color      string
-	WebhookForm
-}
-
-// Validate validates the fields
-func (f *NewSlackHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
-	ctx := context.GetValidateContext(req)
-	if !webhook.IsValidSlackChannel(strings.TrimSpace(f.Channel)) {
-		errs = append(errs, binding.Error{
-			FieldNames:     []string{"Channel"},
-			Classification: "",
-			Message:        ctx.Locale.TrString("repo.settings.add_webhook.invalid_channel_name"),
-		})
-	}
-	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
-}
-
 // NewDiscordHookForm form for creating discord hook
 type NewDiscordHookForm struct {
 	PayloadURL string `binding:"Required;ValidUrl"`
diff --git a/services/webhook/slack.go b/services/webhook/slack.go
index fdc10730de..683ef41019 100644
--- a/services/webhook/slack.go
+++ b/services/webhook/slack.go
@@ -17,14 +17,57 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	webhook_module "code.gitea.io/gitea/modules/webhook"
+	gitea_context "code.gitea.io/gitea/services/context"
+	"code.gitea.io/gitea/services/forms"
+
+	"gitea.com/go-chi/binding"
 )
 
 type slackHandler struct{}
 
 func (slackHandler) Type() webhook_module.HookType { return webhook_module.SLACK }
 
+type slackForm struct {
+	forms.WebhookForm
+	PayloadURL string `binding:"Required;ValidUrl"`
+	Channel    string `binding:"Required"`
+	Username   string
+	IconURL    string
+	Color      string
+}
+
+var _ binding.Validator = &slackForm{}
+
+// Validate implements binding.Validator.
+func (s *slackForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
+	ctx := gitea_context.GetWebContext(req)
+	if !IsValidSlackChannel(strings.TrimSpace(s.Channel)) {
+		errs = append(errs, binding.Error{
+			FieldNames:     []string{"Channel"},
+			Classification: "",
+			Message:        ctx.Locale.TrString("repo.settings.add_webhook.invalid_channel_name"),
+		})
+	}
+	return errs
+}
+
 func (slackHandler) FormFields(bind func(any)) FormFields {
-	panic("TODO")
+	var form slackForm
+	bind(&form)
+
+	return FormFields{
+		WebhookForm: form.WebhookForm,
+		URL:         form.PayloadURL,
+		ContentType: webhook_model.ContentTypeJSON,
+		Secret:      "",
+		HTTPMethod:  http.MethodPost,
+		Metadata: &SlackMeta{
+			Channel:  strings.TrimSpace(form.Channel),
+			Username: form.Username,
+			IconURL:  form.IconURL,
+			Color:    form.Color,
+		},
+	}
 }
 
 // SlackMeta contains the slack metadata