- 订单列表使用独立最小 DTO 并分页,号主待办提供独立接口与统计 - 用户 token 增加版本控制,冻结/改密/退出即时撤销会话 - 移除 URL token 传参,SSE 与接口统一使用 HttpOnly Cookie - 私有文件按上传归属与业务关联授权,收款凭证转私有访问并校验归属 - 公开商品接口返回最小字段,隐藏号主身份与内部状态 - 每日清理超过 30 天未关联业务的上传归属,上传归属失败时补偿删除对象
78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package fileuploadcleanup
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
func TestCleanupOnlyDeletesExpiredUnreferencedUploads(t *testing.T) {
|
|
db := openTestDB(t)
|
|
if err := db.AutoMigrate(&model.FileUploadOwner{}); err != nil {
|
|
t.Fatalf("AutoMigrate() error = %v", err)
|
|
}
|
|
createReferenceTables(t, db)
|
|
now := time.Date(2026, 8, 16, 0, 0, 0, 0, time.UTC)
|
|
old := now.Add(-31 * 24 * time.Hour)
|
|
recent := now.Add(-29 * 24 * time.Hour)
|
|
records := []model.FileUploadOwner{
|
|
{UserID: 1, ObjectKey: "listing/orphan.jpg", CreatedAt: old},
|
|
{UserID: 1, ObjectKey: "listing/referenced.jpg", CreatedAt: old},
|
|
{UserID: 1, ObjectKey: "listing/recent.jpg", CreatedAt: recent},
|
|
}
|
|
if err := db.Create(&records).Error; err != nil {
|
|
t.Fatalf("create upload owners error = %v", err)
|
|
}
|
|
if err := db.Exec("INSERT INTO game_accounts (id, screenshot_urls) VALUES (1, ?)", `["/api/files/object?key=listing%2Freferenced.jpg"]`).Error; err != nil {
|
|
t.Fatalf("create referenced account error = %v", err)
|
|
}
|
|
|
|
job := New(db, nil, nil)
|
|
deleted, err := job.cleanup(context.Background(), now)
|
|
if err != nil {
|
|
t.Fatalf("cleanup() error = %v", err)
|
|
}
|
|
if deleted != 1 {
|
|
t.Fatalf("cleanup() deleted = %d, want 1", deleted)
|
|
}
|
|
var remaining []model.FileUploadOwner
|
|
if err := db.Order("id ASC").Find(&remaining).Error; err != nil {
|
|
t.Fatalf("load remaining uploads error = %v", err)
|
|
}
|
|
if len(remaining) != 2 || remaining[0].ObjectKey != "listing/referenced.jpg" || remaining[1].ObjectKey != "listing/recent.jpg" {
|
|
t.Fatalf("unexpected remaining uploads: %#v", remaining)
|
|
}
|
|
}
|
|
|
|
func openTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite error = %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func createReferenceTables(t *testing.T, db *gorm.DB) {
|
|
t.Helper()
|
|
statements := []string{
|
|
"CREATE TABLE game_accounts (id INTEGER PRIMARY KEY, screenshot_urls TEXT)",
|
|
"CREATE TABLE order_checkouts (id INTEGER PRIMARY KEY, evidence_urls TEXT)",
|
|
"CREATE TABLE disputes (id INTEGER PRIMARY KEY, evidence_urls TEXT)",
|
|
"CREATE TABLE handoff_records (id INTEGER PRIMARY KEY, attachment_urls TEXT)",
|
|
"CREATE TABLE chat_messages (id INTEGER PRIMARY KEY, attachment_urls TEXT)",
|
|
"CREATE TABLE user_payment_accounts (id INTEGER PRIMARY KEY, certificate_urls TEXT)",
|
|
}
|
|
for _, statement := range statements {
|
|
if err := db.Exec(statement).Error; err != nil {
|
|
t.Fatalf("create reference table error = %v", err)
|
|
}
|
|
}
|
|
}
|