fix(platform): enforce identity relations

This commit is contained in:
2026-07-27 02:59:28 +08:00
parent 57f44e0719
commit 08bc6b3ec4
5 changed files with 180 additions and 30 deletions

View File

@@ -25,6 +25,7 @@ import (
func TestExpectedResources(t *testing.T) {
assertContract(t, ExpectedResources(), "gas", "gas_basic", Writable, "list")
assertContract(t, ExpectedResources(), "safety", "saf_event", Writable, "list")
assertContract(t, ExpectedResources(), "ec", "ec_order_item", Writable, "list")
assertContract(t, ExpectedResources(), "wallet", "wallet_ledger", ReadOnly, "list")
}
@@ -183,6 +184,49 @@ func TestGetEcOrderReturnsOrderItems(t *testing.T) {
assertMockExpectations(t, mock)
}
func TestPrepareResourceValuesResolvesRequiredIdentityRelationsAndRejectsInvalidPayloads(t *testing.T) {
_, mock := setupPlatformRoleDatabase(t)
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "id" FROM "ec_order" WHERE identity = $1 ORDER BY "ec_order"."id" LIMIT $2`)).
WithArgs("order-a", 1).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uint64(1)))
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "id" FROM "ec_product" WHERE identity = $1 ORDER BY "ec_product"."id" LIMIT $2`)).
WithArgs("product-a", 1).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uint64(2)))
ctx, _ := updateContext(http.MethodPost, "/ec/ec_order_item", "", []byte(`{"ec_order_identity":"order-a","ec_product_identity":"product-a","quantity":2}`))
values, err := prepareResourceValues(ctx, []string{"quantity"}, []ResourceRelation{
{Input: "ec_order_identity", Column: "ec_order_id", Model: &models.EcOrder{}, Required: true},
{Input: "ec_product_identity", Column: "ec_product_id", Model: &models.EcProduct{}, Required: true},
})
if err != nil {
t.Fatal(err)
}
if values["ec_order_id"] != uint64(1) || values["ec_product_id"] != uint64(2) || values["quantity"] != float64(2) {
t.Fatalf("unexpected resolved values: %#v", values)
}
assertMockExpectations(t, mock)
for _, body := range []string{`{}`, `{"ec_order_id":1}`, `{"quantity":2}`} {
ctx, _ := updateContext(http.MethodPost, "/ec/ec_order_item", "", []byte(body))
if _, err := prepareResourceValues(ctx, []string{"quantity"}, []ResourceRelation{{Input: "ec_order_identity", Column: "ec_order_id", Model: &models.EcOrder{}, Required: true}}); err == nil {
t.Fatalf("payload %s was accepted", body)
}
}
}
func TestResourceResponseDoesNotExposeAutoIncrementRelationIDs(t *testing.T) {
response := resourceResponse(map[string]any{"identity": "item-a", "id": uint64(1), "ec_order_id": uint64(2), "ec_product_id": uint64(3), "items": []any{map[string]any{"identity": "child-a", "delivery_task_id": uint64(4)}}})
encoded, err := json.Marshal(response)
if err != nil {
t.Fatal(err)
}
for _, forbidden := range []string{`"id"`, `"ec_order_id"`, `"ec_product_id"`, `"delivery_task_id"`} {
if strings.Contains(string(encoded), forbidden) {
t.Fatalf("response exposed internal relation key %s: %s", forbidden, encoded)
}
}
}
func TestGetDeliveryTrackOrdersAndMasksPointsWithoutPreciseLocationScope(t *testing.T) {
_, mock := setupPlatformRoleDatabase(t)
now := time.Now().UTC()