feat: initial dummy webhook support. use gitea VerifyWebhookSignatureMiddleware instead.
This commit is contained in:
parent
26f497f062
commit
9262bb0555
|
@ -1,16 +1,11 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
"context"
|
"context"
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"git.lumeweb.com/LumeWeb/gitea-github-proxy/config"
|
"git.lumeweb.com/LumeWeb/gitea-github-proxy/config"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"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) {
|
func addAuthStatusToRequestServ(status bool, r *http.Request, w http.ResponseWriter, next http.Handler) {
|
||||||
ctx := context.WithValue(r.Context(), AUTHED_CONTEXT_KEY, status)
|
ctx := context.WithValue(r.Context(), AUTHED_CONTEXT_KEY, status)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
|
|
|
@ -27,6 +27,7 @@ func SetupRoutes(params RouteParams) {
|
||||||
setupSettingsRoutes(params)
|
setupSettingsRoutes(params)
|
||||||
setupManifestsRoutes(params)
|
setupManifestsRoutes(params)
|
||||||
setupAppRoutes(params)
|
setupAppRoutes(params)
|
||||||
|
setupWebhookRoutes(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientParams struct {
|
type ClientParams struct {
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
4
go.mod
4
go.mod
|
@ -3,9 +3,10 @@ module git.lumeweb.com/LumeWeb/gitea-github-proxy
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
code.gitea.io/gitea/modules/structs v0.0.0-20190610152049-835b53fc259c
|
||||||
code.gitea.io/sdk/gitea v0.17.1
|
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/gorilla/mux v1.8.1
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.18.2
|
||||||
go.uber.org/fx v1.20.1
|
go.uber.org/fx v1.20.1
|
||||||
go.uber.org/zap v1.23.0
|
go.uber.org/zap v1.23.0
|
||||||
|
@ -25,7 +26,6 @@ require (
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.17 // 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/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
|
Loading…
Reference in New Issue