Files
forge/routers/web/misc/sync_test.go
zeekayandHanzo Dev 9a07b4d089 legal: Hanzo AI, Inc. copyright above the upstream notices
2978 files. The fork is 2026-07-15 (rebrand: gitea.dev -> github.com/hanzoai/git),
so 2026 is the year, and "Copyright 2026 Hanzo AI, Inc." was already the form
used by the handful of files that had ours.

Shape is now:

	// Copyright 2026 Hanzo AI, Inc. All rights reserved.
	// Copyright 2015 The Gogs Authors. All rights reserved.
	// Copyright 2019 The Gitea Authors. All rights reserved.
	// SPDX-License-Identifier: MIT

Ours on top, theirs retained verbatim. Retained because MIT requires it, and
separately because they are true — those authors did write that code.

Not renamed to "The Git Authors": Git is a different project under a different
license, and putting its name here would attribute this code to people who have
nothing to do with it. Adding our line is the fix; overwriting theirs would have
been both a licence violation and a false statement.

gofmt still reports import-order drift in some of these files. It predates this
change (verified against a stash) and is left alone rather than burying a
one-line-per-file legal change under 3000 files of unrelated reordering.

Build clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 13:49:52 -07:00

96 lines
3.2 KiB
Go

// Copyright 2026 Hanzo AI, Inc. All rights reserved.
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package misc
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/hanzoai/git/modules/setting"
"github.com/hanzoai/git/modules/test"
"github.com/stretchr/testify/assert"
)
const payload = `{"repository":{"full_name":"o/r"}}`
func sign(secret, body string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(body))
return "sha256=" + hex.EncodeToString(mac.Sum(nil))
}
func TestValidSignature(t *testing.T) {
good := sign("s3cr3t", payload)
assert.True(t, validSignature("s3cr3t", good, []byte(payload)))
assert.False(t, validSignature("other", good, []byte(payload)), "wrong key")
assert.False(t, validSignature("s3cr3t", good, []byte(payload+" ")), "tampered body")
assert.False(t, validSignature("s3cr3t", "", []byte(payload)), "absent header")
assert.False(t, validSignature("s3cr3t", strings.TrimPrefix(good, "sha256="), []byte(payload)), "unprefixed")
assert.False(t, validSignature("s3cr3t", "sha256=zz", []byte(payload)), "non-hex")
assert.False(t, validSignature("", good, []byte(payload)), "empty key never validates")
}
func TestRepoFromPayload(t *testing.T) {
owner, repo, ok := repoFromPayload([]byte(payload))
assert.True(t, ok)
assert.Equal(t, "o", owner)
assert.Equal(t, "r", repo)
for name, body := range map[string]string{
"ping": `{"zen":"Design for failure."}`,
"no slash": `{"repository":{"full_name":"lonely"}}`,
"empty owner": `{"repository":{"full_name":"/r"}}`,
"empty repo": `{"repository":{"full_name":"o/"}}`,
"not an event": `not json`,
} {
_, _, ok := repoFromPayload([]byte(body))
assert.False(t, ok, name)
}
}
func post(t *testing.T, body, sigHeader string) *httptest.ResponseRecorder {
t.Helper()
req := httptest.NewRequest(http.MethodPost, "/v1/sync", strings.NewReader(body))
if sigHeader != "" {
req.Header.Set("X-Hub-Signature-256", sigHeader)
}
w := httptest.NewRecorder()
Sync(w, req)
return w
}
func TestSyncFailsClosed(t *testing.T) {
// No secret: refuse everything, including a payload that would verify
// under some other key.
defer test.MockVariableValue(&setting.Mirror.SyncSecret, "")()
assert.Equal(t, http.StatusServiceUnavailable, post(t, payload, sign("k", payload)).Code)
}
func TestSyncRejectsUnsigned(t *testing.T) {
defer test.MockVariableValue(&setting.Mirror.SyncSecret, "s3cr3t")()
assert.Equal(t, http.StatusUnauthorized, post(t, payload, "").Code, "missing signature")
assert.Equal(t, http.StatusUnauthorized, post(t, payload, sign("wrong", payload)).Code, "wrong key")
assert.Equal(t, http.StatusUnauthorized, post(t, payload+" ", sign("s3cr3t", payload)).Code, "tampered body")
}
func TestSyncPingIsBenign(t *testing.T) {
// A signed event naming no repository must be a 200 no-op, so the hook
// shows healthy upstream.
const ping = `{"zen":"Design for failure."}`
defer test.MockVariableValue(&setting.Mirror.SyncSecret, "s3cr3t")()
w := post(t, ping, sign("s3cr3t", ping))
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "ok", w.Body.String())
}