package main import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "net/http" "net/http/httptest" "strconv" "strings" "testing" "time" ) func TestInternalCultivateRequiresSignedServiceRequest(t *testing.T) { previous := internalAPI defer func() { internalAPI = previous }() internalAPI = internalAPIRuntime{config: internalAPIConfig{Enabled: true, Services: map[string]internalAPIServiceConfig{"hotgo-admin": {Secret: "secret"}}}} req := httptest.NewRequest(http.MethodPost, "/internal/cultivate/tenants/default/users/batch", strings.NewReader(`{"user_ids":[1]}`)) rec := httptest.NewRecorder() serveInternalCultivate(rec, req, "/internal/cultivate/") if rec.Code != http.StatusUnauthorized { t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String()) } } func TestInternalCultivateUsesSharedInternalCredential(t *testing.T) { previous := internalAPI defer func() { internalAPI = previous }() internalAPI = internalAPIRuntime{config: internalAPIConfig{Enabled: true, TimeWindowSeconds: 300, Services: map[string]internalAPIServiceConfig{ "hotgo-admin": {Secret: "shared-secret", Allow: []string{"admin_query"}}, "cultivate-server": {Secret: "ignored-separate-secret", Allow: []string{"cultivate"}}, }}} req := httptest.NewRequest(http.MethodPost, "/internal/cultivate/tenants/default/users/batch", strings.NewReader(`{"user_ids":[1]}`)) req.Header.Set(internalHeaderService, "cultivate-server") timestamp := strconv.FormatInt(time.Now().Unix(), 10) req.Header.Set(internalHeaderTimestamp, timestamp) req.Header.Set(internalHeaderNonce, "nonce") bodyHash := sha256.Sum256([]byte(`{"user_ids":[1]}`)) signingText := strings.Join([]string{req.Method, req.URL.RequestURI(), hex.EncodeToString(bodyHash[:]), timestamp, "nonce"}, "\n") mac := hmac.New(sha256.New, []byte("shared-secret")) _, _ = mac.Write([]byte(signingText)) req.Header.Set(internalHeaderSignature, hex.EncodeToString(mac.Sum(nil))) rec := httptest.NewRecorder() if !authorizeInternalAPI(rec, req) { t.Fatalf("shared internal credential was rejected: status=%d body=%s", rec.Code, rec.Body.String()) } } func TestCultivateFileReferenceTopic(t *testing.T) { first := cultivateFileReferenceTopic(1577072518975639552, 0) second := cultivateFileReferenceTopic(1577072518975639552, 1) if first == second { t.Fatalf("file references must be unique per media item: %q", first) } if len(first) > 25 || len(second) > 25 { t.Fatalf("file reference exceeds im_filemsglinks.topic capacity: %q %q", first, second) } if first != cultivateFileReferenceTopic(1577072518975639552, 0) { t.Fatalf("file reference is not deterministic: %q", first) } }