feat: persist huohanhan auth state in mysql
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user