package customer_binding import ( "context" "database/sql" "database/sql/driver" "io" "testing" "gorm.io/driver/postgres" "gorm.io/gorm" accessauditapp "github.com/break/junhong_cmp_fiber/internal/application/accessaudit" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/pkg/constants" ) func init() { sql.Register("customer_binding_audit_test", customerAuditDriver{}) } type customerAuditDriver struct{} func (customerAuditDriver) Open(string) (driver.Conn, error) { return customerAuditConn{}, nil } type customerAuditConn struct{} func (customerAuditConn) Prepare(string) (driver.Stmt, error) { return nil, driver.ErrSkip } func (customerAuditConn) Close() error { return nil } func (customerAuditConn) Begin() (driver.Tx, error) { return nil, driver.ErrSkip } func (customerAuditConn) QueryContext(context.Context, string, []driver.NamedValue) (driver.Rows, error) { return &customerAuditRows{}, nil } type customerAuditRows struct{ sent bool } func (*customerAuditRows) Columns() []string { return []string{"id", "nickname"} } func (r *customerAuditRows) Close() error { return nil } func (r *customerAuditRows) Next(dest []driver.Value) error { if r.sent { return io.EOF } r.sent = true dest[0], dest[1] = int64(7), "客户" return nil } type captureAuditWriter struct{ change accessauditapp.ChangeAudit } func (w *captureAuditWriter) WriteAccessChange(_ context.Context, _ *gorm.DB, change accessauditapp.ChangeAudit) error { w.change = change return nil } func TestWriteBindingAuditOmitsInternalAssets(t *testing.T) { db, err := sql.Open("customer_binding_audit_test", "") if err != nil { t.Fatal(err) } defer db.Close() tx, err := gorm.Open(postgres.New(postgres.Config{Conn: db}), &gorm.Config{}) if err != nil { t.Fatal(err) } writer := &captureAuditWriter{} service := &Service{accessAudit: writer} personalDevices := []accessauditapp.PersonalCustomerDeviceChange{{Binding: &model.PersonalCustomerDevice{Model: gorm.Model{ID: 2}, CustomerID: 7, VirtualNo: "DEVICE-1"}}} personalICCIDs := []accessauditapp.PersonalCustomerICCIDChange{{Binding: &model.PersonalCustomerICCID{Model: gorm.Model{ID: 3}, CustomerID: 7, ICCID: "ICCID-1"}}} cards := []accessauditapp.IotCardChange{{Card: &model.IotCard{Model: gorm.Model{ID: 9}}}} devices := []accessauditapp.DeviceChange{{Device: &model.Device{Model: gorm.Model{ID: 10}}}} if err := service.writeBindingAudit(context.Background(), tx, constants.AuditActionPersonalCustomerAssetBound, "绑定个人客户资产", 7, personalDevices, personalICCIDs, cards, devices); err != nil { t.Fatalf("写入绑定审计失败: %v", err) } change := writer.change if len(change.Cards) != 0 || len(change.Devices) != 0 { t.Fatalf("绑定审计泄露内部资源: Cards=%d Devices=%d", len(change.Cards), len(change.Devices)) } if change.PersonalCustomer == nil || change.PersonalCustomer.ID != 7 || len(change.PersonalDevices) != 1 || len(change.PersonalICCIDs) != 1 { t.Fatalf("绑定审计未保留个人客户字段: %#v", change) } if change.SubjectData["asset_type"] != constants.AuditResourceIotCard || change.SubjectData["asset_id"] != uint(9) { t.Fatalf("绑定审计未保留主体摘要: %#v", change.SubjectData) } }