diff --git a/api/middleware.go b/api/middleware.go index 1956802..c61d10c 100644 --- a/api/middleware.go +++ b/api/middleware.go @@ -1,16 +1,11 @@ package api import ( - "bytes" "code.gitea.io/sdk/gitea" "context" - "crypto/hmac" - "crypto/sha256" - "encoding/hex" "git.lumeweb.com/LumeWeb/gitea-github-proxy/config" "github.com/gorilla/mux" "go.uber.org/zap" - "io" "net/http" "strings" ) @@ -90,52 +85,6 @@ func loggingMiddleware(logger *zap.Logger) mux.MiddlewareFunc { }) } } - -func giteaVerifyWebhookMiddleware(cfg *config.Config, logger *zap.Logger) mux.MiddlewareFunc { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - signature := r.Header.Get("X-Gitea-Signature") - if signature == "" { - http.Error(w, "No signature provided", http.StatusBadRequest) - return - } - - decodedSignature, err := hex.DecodeString(signature) - if err != nil { - http.Error(w, "Error decoding signature", http.StatusBadRequest) - logger.Error("Error decoding signature", zap.Error(err)) - return - } - - payload, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "Error reading body", http.StatusBadRequest) - logger.Error("Error reading body", zap.Error(err)) - return - } - defer func(body io.ReadCloser) { - err := body.Close() - if err != nil { - logger.Error("Error closing body", zap.Error(err)) - } - }(r.Body) - - r.Body = io.NopCloser(bytes.NewBuffer(payload)) - - mac := hmac.New(sha256.New, []byte(cfg.GiteaWebHookSecret)) - mac.Write(payload) - expectedMAC := mac.Sum(nil) - - if !hmac.Equal(decodedSignature, expectedMAC) { - http.Error(w, "Invalid signature", http.StatusForbidden) - return - } - - next.ServeHTTP(w, r) - }) - } -} - func addAuthStatusToRequestServ(status bool, r *http.Request, w http.ResponseWriter, next http.Handler) { ctx := context.WithValue(r.Context(), AUTHED_CONTEXT_KEY, status) r = r.WithContext(ctx) diff --git a/api/routes.go b/api/routes.go index e15603c..9d9cab5 100644 --- a/api/routes.go +++ b/api/routes.go @@ -27,6 +27,7 @@ func SetupRoutes(params RouteParams) { setupSettingsRoutes(params) setupManifestsRoutes(params) setupAppRoutes(params) + setupWebhookRoutes(params) } type ClientParams struct { diff --git a/api/routes_webhooks.go b/api/routes_webhooks.go new file mode 100644 index 0000000..f78ed33 --- /dev/null +++ b/api/routes_webhooks.go @@ -0,0 +1,49 @@ +package api + +import ( + "code.gitea.io/sdk/gitea" + "encoding/json" + "git.lumeweb.com/LumeWeb/gitea-github-proxy/config" + "go.uber.org/zap" + "gorm.io/gorm" + "io" + "net/http" +) + +type webhookApi struct { + config *config.Config + logger *zap.Logger + db *gorm.DB +} + +func newWebhookApi(cfg *config.Config, db *gorm.DB, logger *zap.Logger) *webhookApi { + return &webhookApi{config: cfg, db: db, logger: logger} +} + +func (a *webhookApi) handleWebhook(w http.ResponseWriter, r *http.Request) { + body, _ := io.ReadAll(r.Body) + + var webhook map[string]interface{} + err := json.Unmarshal(body, &webhook) + if err != nil { + a.logger.Error("Failed to unmarshal webhook", zap.Error(err)) + w.WriteHeader(http.StatusInternalServerError) + return + } + + a.logger.Debug("Received webhook", zap.Any("webhook", webhook)) +} + +func setupWebhookRoutes(params RouteParams) { + cfg := params.Config + db := params.Db + logger := params.Logger + r := params.R + + webhookApi := newWebhookApi(cfg, db, logger) + webhookRouter := r.PathPrefix("/api").Subrouter() + + webhookRouter.Use(gitea.VerifyWebhookSignatureMiddleware(cfg.GiteaWebHookSecret)) + + webhookRouter.HandleFunc("/webhook", webhookApi.handleWebhook).Methods("POST") +} diff --git a/go.mod b/go.mod index c01590c..9235701 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module git.lumeweb.com/LumeWeb/gitea-github-proxy go 1.21 require ( + code.gitea.io/gitea/modules/structs v0.0.0-20190610152049-835b53fc259c code.gitea.io/sdk/gitea v0.17.1 - github.com/golang-jwt/jwt/v5 v5.2.0 github.com/gorilla/mux v1.8.1 + github.com/mitchellh/mapstructure v1.5.0 github.com/spf13/viper v1.18.2 go.uber.org/fx v1.20.1 go.uber.org/zap v1.23.0 @@ -25,7 +26,6 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-sqlite3 v1.14.17 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect