Files
heicode-win/heicode/controller/resource_test.go
T

144 lines
4.6 KiB
Go

package controller
import (
"bytes"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"github.com/gin-gonic/gin"
"github.com/glebarez/sqlite"
"github.com/heicode/manager/common"
"github.com/heicode/manager/model"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
func TestNormalizeResourcePayloadAcceptsP1ResourceModel(t *testing.T) {
payload, err := normalizeResourcePayload(resourcePayload{
TenantId: " tenant-a ",
ProjectId: " project-a ",
Name: " repo ",
Type: model.ResourceTypeGit,
Target: "https://github.com/example/repo",
Metadata: map[string]any{
"repo_url": "https://github.com/example/repo",
"ref": "main",
},
Scopes: []string{" read ", "write", "read", ""},
Constraints: map[string]any{
"allowed_paths": []any{".", "docs"},
},
SecretRef: "vault://tenant-a/git/repo",
})
require.NoError(t, err)
require.Equal(t, "tenant-a", payload.TenantId)
require.Equal(t, "project-a", payload.ProjectId)
require.Equal(t, "custom", payload.Provider)
require.Equal(t, "active", payload.Status)
require.Equal(t, []string{"read", "write"}, payload.Scopes)
}
func TestNormalizeResourcePayloadRejectsRawSecretMaterial(t *testing.T) {
_, err := normalizeResourcePayload(resourcePayload{
TenantId: "tenant-a",
ProjectId: "project-a",
Name: "cloud",
Type: model.ResourceTypeCloudAccount,
Target: "azure-subscription-1",
Metadata: map[string]any{
"access_token": "must-not-be-saved",
},
})
require.Error(t, err)
require.Contains(t, err.Error(), "must not contain raw secret material")
}
func TestNormalizeResourceGrantPayloadRequiresAgnetRoleBinding(t *testing.T) {
payload, err := normalizeResourceGrantPayload(resourceGrantPayload{
TenantId: "tenant-a",
ProjectId: "project-a",
ResourceId: 42,
AgnetId: "builder-1",
Role: "developer",
Scopes: []string{"read", "read", "write"},
})
require.NoError(t, err)
require.Equal(t, []string{"read", "write"}, payload.Scopes)
require.Equal(t, "active", payload.Status)
}
func TestResourceHandlersCreateResourceAndGrant(t *testing.T) {
originalDB := model.DB
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
require.NoError(t, db.AutoMigrate(&model.Resource{}, &model.ResourceGrant{}))
model.DB = db
t.Cleanup(func() { model.DB = originalDB })
resourceBody := []byte(`{
"tenant_id":"tenant-a",
"project_id":"project-a",
"name":"repo",
"type":"git",
"target":"https://github.com/example/repo",
"metadata":{"repo_url":"https://github.com/example/repo","ref":"main"},
"scopes":["read","write"],
"constraints":{"allowed_paths":["."]},
"secret_ref":"vault://tenant-a/git/repo"
}`)
resourceRecorder := callResourceHandler(t, http.MethodPost, "/api/resources/", resourceBody, CreateResource)
var resourceEnvelope struct {
Success bool `json:"success"`
Data struct {
Id int `json:"id"`
SecretRef string `json:"secret_ref"`
Scopes []string `json:"scopes"`
} `json:"data"`
}
require.NoError(t, common.Unmarshal(resourceRecorder.Body.Bytes(), &resourceEnvelope))
require.True(t, resourceEnvelope.Success)
require.NotZero(t, resourceEnvelope.Data.Id)
require.Equal(t, "vault://tenant-a/git/repo", resourceEnvelope.Data.SecretRef)
require.Equal(t, []string{"read", "write"}, resourceEnvelope.Data.Scopes)
grantBody := []byte(`{
"tenant_id":"tenant-a",
"project_id":"project-a",
"resource_id":` + strconv.Itoa(resourceEnvelope.Data.Id) + `,
"agnet_id":"builder-1",
"role":"developer",
"scopes":["read"]
}`)
grantRecorder := callResourceHandler(t, http.MethodPost, "/api/resource-grants/", grantBody, CreateResourceGrant)
var grantEnvelope struct {
Success bool `json:"success"`
Data struct {
ResourceId int `json:"resource_id"`
AgnetId string `json:"agnet_id"`
Role string `json:"role"`
} `json:"data"`
}
require.NoError(t, common.Unmarshal(grantRecorder.Body.Bytes(), &grantEnvelope))
require.True(t, grantEnvelope.Success)
require.Equal(t, resourceEnvelope.Data.Id, grantEnvelope.Data.ResourceId)
require.Equal(t, "builder-1", grantEnvelope.Data.AgnetId)
require.Equal(t, "developer", grantEnvelope.Data.Role)
}
func callResourceHandler(t *testing.T, method string, target string, body []byte, handler gin.HandlerFunc) *httptest.ResponseRecorder {
t.Helper()
gin.SetMode(gin.TestMode)
recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.Request = httptest.NewRequest(method, target, bytes.NewReader(body))
ctx.Request.Header.Set("Content-Type", "application/json")
ctx.Set("id", 7)
handler(ctx)
return recorder
}