omx(team): auto-checkpoint worker-4 [4]

This commit is contained in:
gongzhiyong
2026-05-02 23:28:37 +08:00
parent 30e0b0b4c6
commit a8be398087
3 changed files with 160 additions and 0 deletions
+140
View File
@@ -0,0 +1,140 @@
package controller
import (
"net/http"
"testing"
"github.com/heicode/manager/common"
"github.com/heicode/manager/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setupResourceControllerTestDB(t *testing.T) {
t.Helper()
db := openTokenControllerTestDB(t)
require.NoError(t, db.AutoMigrate(&model.ResourceBinding{}, &model.ResourceGrant{}))
}
func decodeResourceBindingData(t *testing.T, raw []byte) resourceBindingResponse {
t.Helper()
var response tokenAPIResponse
require.NoError(t, common.Unmarshal(raw, &response))
require.True(t, response.Success, response.Message)
var data resourceBindingResponse
require.NoError(t, common.Unmarshal(response.Data, &data))
return data
}
func decodeResourceGrantData(t *testing.T, raw []byte) resourceGrantResponse {
t.Helper()
var response tokenAPIResponse
require.NoError(t, common.Unmarshal(raw, &response))
require.True(t, response.Success, response.Message)
var data resourceGrantResponse
require.NoError(t, common.Unmarshal(response.Data, &data))
return data
}
func TestCreateResourceAcceptsSecretRefOnly(t *testing.T) {
setupResourceControllerTestDB(t)
body := map[string]any{
"tenant_id": "tenant-a",
"project_id": "project-a",
"resource_type": "git",
"name": "main repo",
"provider": "github",
"resource_ref": "https://github.com/example/repo.git",
"metadata": map[string]any{
"ref": "main",
},
"permission_scope": map[string]any{
"actions": []string{"read", "write"},
},
"constraints": map[string]any{
"paths": []string{"src"},
},
"secret_ref": "vault://tenant-a/git/main-repo",
}
ctx, recorder := newAuthenticatedContext(t, http.MethodPost, "/api/resources/", body, 7)
CreateResource(ctx)
data := decodeResourceBindingData(t, recorder.Body.Bytes())
assert.Equal(t, 7, data.UserId)
assert.Equal(t, "tenant-a", data.TenantId)
assert.Equal(t, "project-a", data.ProjectId)
assert.Equal(t, "git", data.ResourceType)
assert.Equal(t, "vault://tenant-a/git/main-repo", data.SecretRef)
assert.Equal(t, "main", data.Metadata["ref"])
assert.NotContains(t, recorder.Body.String(), "plain-token")
}
func TestCreateResourceRejectsPlaintextSecret(t *testing.T) {
setupResourceControllerTestDB(t)
body := map[string]any{
"tenant_id": "tenant-a",
"project_id": "project-a",
"resource_type": "cloud_account",
"name": "aws account",
"resource_ref": "arn:aws:organizations::123456789012:account/o-example/123456789012",
"secret": "plain-token",
}
ctx, recorder := newAuthenticatedContext(t, http.MethodPost, "/api/resources/", body, 7)
CreateResource(ctx)
var response tokenAPIResponse
require.NoError(t, common.Unmarshal(recorder.Body.Bytes(), &response))
assert.False(t, response.Success)
assert.Contains(t, response.Message, "secret plaintext is not accepted")
assert.NotContains(t, recorder.Body.String(), "plain-token")
}
func TestCreateResourceGrantBindsProjectRoleAndSubAgnet(t *testing.T) {
setupResourceControllerTestDB(t)
resource := model.ResourceBinding{
UserId: 7,
TenantId: "tenant-a",
ProjectId: "project-a",
ResourceType: "cloud_resource",
Name: "staging vm",
Provider: "azure",
ResourceRef: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/vm-a",
Metadata: "{}",
PermissionScope: "{}",
Constraints: "{}",
Status: "active",
SecretRef: "vault://tenant-a/azure/vm-a",
}
require.NoError(t, model.DB.Create(&resource).Error)
body := map[string]any{
"tenant_id": "tenant-a",
"project_id": "project-a",
"resource_id": resource.Id,
"role": "frontend-developer",
"sub_agnet_id": "agnet-worker-1",
"permission_scope": map[string]any{
"actions": []string{"read", "deploy"},
},
"constraints": map[string]any{
"environment": "staging",
},
"audit_note": "grant for deployment smoke test",
}
ctx, recorder := newAuthenticatedContext(t, http.MethodPost, "/api/resource-grants/", body, 7)
CreateResourceGrant(ctx)
data := decodeResourceGrantData(t, recorder.Body.Bytes())
assert.Equal(t, "tenant-a", data.TenantId)
assert.Equal(t, "project-a", data.ProjectId)
assert.Equal(t, resource.Id, data.ResourceId)
assert.Equal(t, "frontend-developer", data.Role)
assert.Equal(t, "agnet-worker-1", data.SubAgnetId)
assert.Equal(t, "staging", data.Constraints["environment"])
}
+4
View File
@@ -281,6 +281,8 @@ func migrateDB() error {
&CustomOAuthProvider{},
&UserOAuthBinding{},
&GitSource{},
&ResourceBinding{},
&ResourceGrant{},
)
if err != nil {
return err
@@ -330,6 +332,8 @@ func migrateDBFast() error {
{&CustomOAuthProvider{}, "CustomOAuthProvider"},
{&UserOAuthBinding{}, "UserOAuthBinding"},
{&GitSource{}, "GitSource"},
{&ResourceBinding{}, "ResourceBinding"},
{&ResourceGrant{}, "ResourceGrant"},
}
// 动态计算migration数量,确保errChan缓冲区足够大
errChan := make(chan error, len(migrations))
+16
View File
@@ -184,6 +184,22 @@ func SetApiRouter(router *gin.Engine) {
gitSourceRoute.DELETE("/:id", controller.DeleteGitSource)
}
resourceRoute := apiRouter.Group("/resources")
resourceRoute.Use(middleware.UserAuth())
{
resourceRoute.GET("/", controller.ListResources)
resourceRoute.POST("/", controller.CreateResource)
resourceRoute.DELETE("/:id", controller.DeleteResource)
}
resourceGrantRoute := apiRouter.Group("/resource-grants")
resourceGrantRoute.Use(middleware.UserAuth())
{
resourceGrantRoute.GET("/", controller.ListResourceGrants)
resourceGrantRoute.POST("/", controller.CreateResourceGrant)
resourceGrantRoute.DELETE("/:id", controller.DeleteResourceGrant)
}
optionRoute := apiRouter.Group("/option")
optionRoute.Use(middleware.RootAuth())
{