53 lines
1.1 KiB
Go
53 lines
1.1 KiB
Go
package forgejo
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type WebhookPayload struct {
|
|
Action string `json:"action"`
|
|
Issue WebhookIssue `json:"issue"`
|
|
}
|
|
|
|
type WebhookIssue struct {
|
|
Number int64 `json:"number"`
|
|
Title string `json:"title"`
|
|
State string `json:"state"`
|
|
}
|
|
|
|
func VerifyWebhookSignature(r *http.Request, secret string) ([]byte, error) {
|
|
signature := r.Header.Get("X-Forgejo-Signature")
|
|
if signature == "" {
|
|
return nil, fmt.Errorf("missing X-Forgejo-Signature header")
|
|
}
|
|
|
|
body, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read body: %w", err)
|
|
}
|
|
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
mac.Write(body)
|
|
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
|
|
|
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
|
|
return nil, fmt.Errorf("invalid signature")
|
|
}
|
|
|
|
return body, nil
|
|
}
|
|
|
|
func ParseWebhookPayload(data []byte) (*WebhookPayload, error) {
|
|
var payload WebhookPayload
|
|
if err := json.Unmarshal(data, &payload); err != nil {
|
|
return nil, fmt.Errorf("parse webhook payload: %w", err)
|
|
}
|
|
return &payload, nil
|
|
}
|