diff --git a/app/admin/apis/shopee_product.go b/app/admin/apis/shopee_product.go index 7e8fe54..da9d4a5 100644 --- a/app/admin/apis/shopee_product.go +++ b/app/admin/apis/shopee_product.go @@ -11,7 +11,6 @@ import ( "go-admin/internal/config" "go-admin/internal/huohanhan" "go-admin/internal/logx" - "go-admin/internal/store" "gorm.io/gorm" "strings" ) @@ -39,12 +38,16 @@ func (e ShopeeProduct) GetByShopeeID(c *gin.Context) { e.Error(401, fmt.Errorf("invalid api key"), "未授权") return } - state, err := store.Open("temp/huohanhan-state.db") + db := primaryDB() + if db == nil { + e.Error(500, fmt.Errorf("database is not initialized"), "数据库未初始化") + return + } + state, err := huohanhan.NewMySQLStateStore(db) if err != nil { e.Error(500, err, "认证存储初始化失败") return } - defer state.Close() cfg := config.HuohanhanConfig{BaseURL: ext.ExtConfig.Huohanhan.BaseURL, Account: ext.ExtConfig.Huohanhan.Account, Password: ext.ExtConfig.Huohanhan.Password, OCRURL: ext.ExtConfig.Huohanhan.OCRURL} logger := logx.New(1000) auth := huohanhan.NewAuthManager(cfg, state, logger, huohanhan.AuthOptions{}) @@ -83,11 +86,6 @@ func (e ShopeeProduct) GetByShopeeID(c *gin.Context) { if v, ok := record["itemStatus"].(string); ok { row.Status = v } - db := primaryDB() - if db == nil { - e.Error(500, fmt.Errorf("database is not initialized"), "数据库未初始化") - return - } if err = db.AutoMigrate(&models.ShopeeProduct{}); err != nil { e.Error(500, err, "数据库初始化失败") return diff --git a/internal/huohanhan/auth.go b/internal/huohanhan/auth.go index 241b0ff..daf9f32 100644 --- a/internal/huohanhan/auth.go +++ b/internal/huohanhan/auth.go @@ -16,6 +16,7 @@ import ( "crypto/rand" "encoding/hex" "encoding/json" + "errors" "fmt" "io" "mime/multipart" @@ -31,7 +32,7 @@ import ( "go-admin/internal/config" "go-admin/internal/logx" - "go-admin/internal/store" + "gorm.io/gorm" ) const ( @@ -71,6 +72,61 @@ type AuthState struct { Cookies map[string]string `json:"cookies"` } +// StateStore stores the serialized Huohanhan authentication state. +// The production adapter uses the GoAdmin MySQL database; the SQLite Store +// still satisfies this interface for isolated package tests and desktop tools. +type StateStore interface { + SetKV(key, value, now string) error + GetKV(key string) (string, bool, error) +} + +type mysqlStateStore struct{ db *gorm.DB } + +type mysqlStateRow struct { + Key string `gorm:"column:state_key;primaryKey;size:128"` + Value string `gorm:"column:state_value;type:longtext;not null"` + UpdatedAt string `gorm:"column:updated_at;size:64;not null"` +} + +func (mysqlStateRow) TableName() string { return "huohanhan_auth_state" } + +// NewMySQLStateStore creates a state store backed by the primary GoAdmin DB. +func NewMySQLStateStore(db *gorm.DB) (StateStore, error) { + if db == nil { + return nil, fmt.Errorf("数据库未初始化") + } + migrationErr := db.AutoMigrate(&mysqlStateRow{}) + if migrationErr != nil { + return nil, fmt.Errorf("初始化货憨憨认证状态表失败:%v", migrationErr) + } + return mysqlStateStore{db: db}, nil +} + +func (s mysqlStateStore) SetKV(key, value, now string) error { + var row mysqlStateRow + result := s.db.Where("state_key = ?", key).First(&row) + if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { + return result.Error + } + row.Key, row.Value, row.UpdatedAt = key, value, now + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return s.db.Create(&row).Error + } + return s.db.Save(&row).Error +} + +func (s mysqlStateStore) GetKV(key string) (string, bool, error) { + var row mysqlStateRow + err := s.db.Where("state_key = ?", key).First(&row).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return "", false, nil + } + if err != nil { + return "", false, err + } + return row.Value, true, nil +} + // AuthorizationValue 返回业务请求使用的 Authorization 值。 func (s AuthState) AuthorizationValue() string { tokenType := strings.TrimSpace(s.TokenType) @@ -92,7 +148,7 @@ func (s AuthState) Expired(now time.Time, skew time.Duration) bool { // AuthManager 串行管理内存与 SQLite 中的认证状态。 type AuthManager struct { cfg config.HuohanhanConfig - db *store.Store + db StateStore log *logx.Logger httpClient *http.Client attempts int @@ -104,7 +160,7 @@ type AuthManager struct { } // NewAuthManager 创建认证管理器。opts 的零值会补成默认配置。 -func NewAuthManager(cfg config.HuohanhanConfig, db *store.Store, logger *logx.Logger, opts AuthOptions) *AuthManager { +func NewAuthManager(cfg config.HuohanhanConfig, db StateStore, logger *logx.Logger, opts AuthOptions) *AuthManager { timeout := opts.RequestTimeout if timeout <= 0 { timeout = defaultRequestTimeout @@ -653,4 +709,3 @@ func newUUID() (string, error) { encoded := hex.EncodeToString(raw[:]) return encoded[0:8] + "-" + encoded[8:12] + "-" + encoded[12:16] + "-" + encoded[16:20] + "-" + encoded[20:32], nil } -