fix: close platform admin final audit findings
This commit is contained in:
@@ -27,6 +27,7 @@ func TestExpectedResources(t *testing.T) {
|
||||
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")
|
||||
assertContract(t, ExpectedResources(), "delivery", "delivery_track_point", ReadOnly, "list")
|
||||
}
|
||||
|
||||
func TestResourceDefinitionAllowsOnlySupportedMethods(t *testing.T) {
|
||||
@@ -238,10 +239,37 @@ func TestCreateGasAccountResolvesGasBasicIdentityBeforePersisting(t *testing.T)
|
||||
mock.ExpectQuery(`INSERT INTO "gas_account"`).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(uint64(1)))
|
||||
mock.ExpectCommit()
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "id","identity" FROM "gas_basic" WHERE id IN ($1)`)).
|
||||
WithArgs(uint64(8)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity"}).AddRow(uint64(8), "gas-a"))
|
||||
|
||||
ctx, recorder := updateContext(http.MethodPost, "/gas/gas_account", "", []byte(`{"username":"operator","password":"password-123","gas_basic_identity":"gas-a"}`))
|
||||
CreateGasAccount(ctx)
|
||||
|
||||
assertResponseCode(t, recorder, 0)
|
||||
body := recorder.Body.String()
|
||||
if !strings.Contains(body, `"identity"`) || !strings.Contains(body, `"gas_basic_identity":"gas-a"`) {
|
||||
t.Fatalf("create response omitted public identities: %s", body)
|
||||
}
|
||||
if strings.Contains(body, `"gas_basic_id"`) || strings.Contains(body, `"password_hash"`) {
|
||||
t.Fatalf("create response exposed internal or sensitive fields: %s", body)
|
||||
}
|
||||
assertMockExpectations(t, mock)
|
||||
}
|
||||
|
||||
func TestListGasAccountAppliesKeywordToCountAndRows(t *testing.T) {
|
||||
_, mock := setupPlatformRoleDatabase(t)
|
||||
keywordWhere := ` WHERE (LOWER("username") LIKE $1 OR LOWER("display_name") LIKE $2 OR LOWER("role_code") LIKE $3)`
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "gas_account"`+keywordWhere)).
|
||||
WithArgs("%operator%", "%operator%", "%operator%").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "gas_account"`+keywordWhere+` ORDER BY created_at desc LIMIT $4`)).
|
||||
WithArgs("%operator%", "%operator%", "%operator%", 20).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "created_at", "updated_at", "status", "version", "gas_basic_id", "username", "display_name", "password_hash", "role_code"}))
|
||||
|
||||
ctx, recorder := updateContext(http.MethodGet, "/gas/gas_account?keyword=Operator", "", nil)
|
||||
ListGasAccount(ctx)
|
||||
|
||||
assertResponseCode(t, recorder, 0)
|
||||
assertMockExpectations(t, mock)
|
||||
}
|
||||
@@ -276,6 +304,30 @@ func TestResourceResponseDoesNotExposeAutoIncrementRelationIDs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatedResourceResponseMasksSensitiveFieldsAndKeepsIdentity(t *testing.T) {
|
||||
response := maskCreatedSensitiveFields(map[string]any{
|
||||
"identity": "user-a",
|
||||
"phone": "13800138000",
|
||||
"real_name": "张三",
|
||||
"credential_no": "CERT-123456",
|
||||
"longitude": "120.123456",
|
||||
"latitude": "30.456789",
|
||||
})
|
||||
encoded, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body := string(encoded)
|
||||
if !strings.Contains(body, `"identity":"user-a"`) || !strings.Contains(body, `"phone_masked":"138****8000"`) {
|
||||
t.Fatalf("created response omitted identity or masked phone: %s", body)
|
||||
}
|
||||
for _, forbidden := range []string{`"phone":`, `"real_name":`, `"credential_no":`, `"longitude":`, `"latitude":`, "张三", "CERT-123456", "120.123456", "30.456789"} {
|
||||
if strings.Contains(body, forbidden) {
|
||||
t.Fatalf("created response exposed sensitive field %s: %s", forbidden, body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSafetyEventDisposalsReturnsOnlyTheRequestedEventHistory(t *testing.T) {
|
||||
_, mock := setupPlatformRoleDatabase(t)
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "saf_event_disposal" WHERE saf_event_identity = $1`)).
|
||||
@@ -392,6 +444,55 @@ func TestGetDeliveryTrackOrdersAndMasksPointsWithoutPreciseLocationScope(t *test
|
||||
assertMockExpectations(t, mock)
|
||||
}
|
||||
|
||||
func TestListDeliveryTrackPointsMasksCoordinatesWithoutPreciseLocationScope(t *testing.T) {
|
||||
_, mock := setupPlatformRoleDatabase(t)
|
||||
now := time.Now().UTC()
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "delivery_track_point"`)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "delivery_track_point" ORDER BY created_at desc LIMIT $1`)).
|
||||
WithArgs(20).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "created_at", "updated_at", "status", "version", "delivery_track_id", "point_type", "occurred_at", "longitude", "latitude"}).
|
||||
AddRow(uint64(9), "point-a", now, now, "enabled", 1, uint64(7), "arrival", now, "120.123456", "30.456789"))
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "id","identity" FROM "delivery_track" WHERE id IN ($1)`)).
|
||||
WithArgs(uint64(7)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity"}).AddRow(uint64(7), "track-a"))
|
||||
|
||||
ctx, recorder := updateContext(http.MethodGet, "/delivery/delivery_track_point", "", nil)
|
||||
listResource(ctx, &models.DeliveryTrackPoint{})
|
||||
|
||||
assertResponseCode(t, recorder, 0)
|
||||
body := recorder.Body.String()
|
||||
if strings.Contains(body, "120.123456") || strings.Contains(body, "30.456789") {
|
||||
t.Fatalf("track-point list exposed precise coordinates without scope: %s", body)
|
||||
}
|
||||
if !strings.Contains(body, `"delivery_track_identity":"track-a"`) {
|
||||
t.Fatalf("track-point list omitted its public relation identity: %s", body)
|
||||
}
|
||||
assertMockExpectations(t, mock)
|
||||
}
|
||||
|
||||
func TestGetDeliveryTrackPointReturnsCoordinatesWithPreciseLocationScope(t *testing.T) {
|
||||
_, mock := setupPlatformRoleDatabase(t)
|
||||
now := time.Now().UTC()
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "delivery_track_point" WHERE identity = $1 ORDER BY "delivery_track_point"."id" LIMIT $2`)).
|
||||
WithArgs("point-a", 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "created_at", "updated_at", "status", "version", "delivery_track_id", "point_type", "occurred_at", "longitude", "latitude"}).
|
||||
AddRow(uint64(9), "point-a", now, now, "enabled", 1, uint64(7), "arrival", now, "120.123456", "30.456789"))
|
||||
mock.ExpectQuery(regexp.QuoteMeta(`SELECT "id","identity" FROM "delivery_track" WHERE id IN ($1)`)).
|
||||
WithArgs(uint64(7)).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "identity"}).AddRow(uint64(7), "track-a"))
|
||||
|
||||
ctx, recorder := updateContext(http.MethodGet, "/delivery/delivery_track_point/point-a", "point-a", nil)
|
||||
ctx.Set("Auth", &types.JwtClaims{Extend: map[string]string{"location_scope": "precise"}})
|
||||
getResource(ctx, &models.DeliveryTrackPoint{})
|
||||
|
||||
assertResponseCode(t, recorder, 0)
|
||||
if !strings.Contains(recorder.Body.String(), "120.123456") || !strings.Contains(recorder.Body.String(), "30.456789") {
|
||||
t.Fatalf("authorized track-point detail omitted precise coordinates: %s", recorder.Body.String())
|
||||
}
|
||||
assertMockExpectations(t, mock)
|
||||
}
|
||||
|
||||
func TestDisposeSafetyEventUpdatesEventAndAppendsOperatorActionTransactionally(t *testing.T) {
|
||||
_, mock := setupPlatformRoleDatabase(t)
|
||||
now := time.Now().UTC()
|
||||
|
||||
Reference in New Issue
Block a user