audit full project flows and harden backend

This commit is contained in:
2026-08-03 16:03:44 +08:00
parent d8d62469d6
commit 95b6f2b69c
22 changed files with 505 additions and 890 deletions

View File

@@ -196,7 +196,7 @@ func migrateDatabase() error {
if err := prepareAdditiveMigrations(migrationDatabase, driver); err != nil {
return err
}
if err := resetLegacyPaymentSchema(migrationDatabase, driver); err != nil {
if err := rejectLegacyPaymentSchema(migrationDatabase); err != nil {
return err
}
const legacyPhoneIndex = "idx_platform_account_phone"
@@ -216,25 +216,12 @@ func migrateDatabase() error {
return initdb.New(databaseService)
}
// resetLegacyPaymentSchema 执行经业务明确授权的开发期破坏性支付模型重置,不迁移旧支付或退款历史
func resetLegacyPaymentSchema(databaseService *gorm.DB, driver string) error {
statements := []string{}
if driver == "postgres" {
statements = append(statements,
`DROP TABLE IF EXISTS "wallet_refund" CASCADE`,
`DROP TABLE IF EXISTS "wallet_payment" CASCADE`,
`DROP TABLE IF EXISTS "gasorder_payment" CASCADE`,
)
} else {
statements = append(statements,
`DROP TABLE IF EXISTS wallet_refund`,
`DROP TABLE IF EXISTS wallet_payment`,
`DROP TABLE IF EXISTS gasorder_payment`,
)
}
for _, statement := range statements {
if err := databaseService.Exec(statement).Error; err != nil {
return fmt.Errorf("reset legacy payment schema: %w", err)
// rejectLegacyPaymentSchema 阻止通用迁移物理删除历史资金表
// 旧支付事实必须通过单独评审的数据迁移保留和对账,不能由 migrate 命令静默重置。
func rejectLegacyPaymentSchema(databaseService *gorm.DB) error {
for _, table := range []string{"wallet_refund", "wallet_payment", "gasorder_payment"} {
if databaseService.Migrator().HasTable(table) {
return fmt.Errorf("检测到历史资金表 %s请先执行经财务与审计批准的保留式迁移", table)
}
}
return nil

View File

@@ -1,18 +1,31 @@
package main
import (
"regexp"
"testing"
"gorm.io/driver/sqlite"
"github.com/DATA-DOG/go-sqlmock"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestPrepareAdditiveMigrationsSkipsMissingLegacyTable(t *testing.T) {
databaseService, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
sqlDatabase, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("open sqlite database: %v", err)
t.Fatalf("open sql mock: %v", err)
}
defer sqlDatabase.Close()
mock.ExpectQuery(regexp.QuoteMeta("SELECT count(*) FROM information_schema.tables WHERE table_schema = CURRENT_SCHEMA() AND table_name = $1 AND table_type = $2")).
WithArgs("gasorder_track_point", "BASE TABLE").
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
databaseService, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDatabase}), &gorm.Config{})
if err != nil {
t.Fatalf("open postgres mock: %v", err)
}
if err := prepareAdditiveMigrations(databaseService, "postgres"); err != nil {
t.Fatalf("missing legacy table should not require a backfill: %v", err)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatalf("unexpected migration query: %v", err)
}
}