diff --git a/model/killara_customer_token_logic.go b/model/killara_customer_token_logic.go index 6f3b0a0..682ed3b 100644 --- a/model/killara_customer_token_logic.go +++ b/model/killara_customer_token_logic.go @@ -3,8 +3,10 @@ package model import ( "encoding/json" "errors" + "fmt" "time" + "github.com/iapologizewhenimwrong/Vestmore_GO/utils/log" "gorm.io/gorm" ) @@ -14,51 +16,67 @@ type KillaraCustomerTokenModel struct { TableName string // 表名 } -// InsertToken inserts a new token record -// func (m *KillaraCustomerTokenModel) InsertToken(data map[string]interface{}) error { -// token, ok := data["token"].(string) -// if !ok { -// return ErrInvalidTokenValue +// 旧的php逻辑 不是一致操作, 存在bug的可能性. +// func (m *KillaraCustomerTokenModel) InsertToken(data *KillaraCustomerToken) error { +// // 删除重复的 token + +// m.DeleteToken(*data.Token) + +// // 删除相同客户ID和平台的旧 token +// if *data.CustomerId != 0 && *data.Platform != 0 { +// m.db.Where("customer_id = ? AND platform = ?", *data.CustomerId, *data.Platform).Delete(&KillaraCustomerToken{}) // } -// m.DeleteToken(token) - -// customerID, _ := data["customer_id"].(uint64) -// platform, _ := data["platform"].(int64) -// if customerID != 0 && platform != 0 { -// m.db.Where("customer_id = ? AND platform = ?", customerID, platform).Delete(&KillaraCustomerToken{}) -// } - -// return m.db.Create(&KillaraCustomerToken{ -// Token: &token, -// CustomerId: &customerID, -// Data: nilStringPtr(data["data"].(string)), -// Expiry: nilTimePtr(time.Unix(int64(data["expiry"].(float64)), 0)), -// Platform: platform, -// }).Error +// return m.db.Create(data).Error // } -// UpdateTokenData updates the data field of a token record +func (m *KillaraCustomerTokenModel) InsertToken(data *KillaraCustomerToken) error { + return m.db.Model(&KillaraCustomerToken{}).Transaction(func(tx *gorm.DB) error { + // 查找是否存在相同客户ID、平台和Token的记录 + var existingToken KillaraCustomerToken + err := tx.Where("customer_id = ? AND platform = ? AND token = ?", data.CustomerId, data.Platform, *data.Token).First(&existingToken).Error + + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + tx.Rollback() // 发生错误,回滚事务 + return err + } + + if !errors.Is(err, gorm.ErrRecordNotFound) { + // 存在记录,先删除 + err = tx.Delete(&existingToken).Error + if err != nil { + tx.Rollback() // 删除错误,回滚事务 + return err + } + } + + // 插入新记录 + err = tx.Create(data).Error + if err != nil { + tx.Rollback() // 插入错误,回滚事务 + return err + } + + return tx.Commit().Error // 提交事务 + }) +} + func (m *KillaraCustomerTokenModel) UpdateTokenData(token string, data map[string]interface{}) error { - dataStr, _ := json.Marshal(data) - return m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("data", string(dataStr)).Error -} - -// UpdateTokenExpiry updates the expiry field of a token record -func (m *KillaraCustomerTokenModel) UpdateTokenExpiry(token string, expiry int64) error { - return m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("expiry", time.Unix(expiry, 0)).Error -} - -// UpdateTokenCustomerID updates the customer_id field of a token record -func (m *KillaraCustomerTokenModel) UpdateTokenCustomerID(token string, customerID uint64) error { - err := m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("customer_id", customerID).Error - if err == gorm.ErrRecordNotFound { - return nil + dataJSON, err := json.Marshal(data) + if err != nil { + return err } - return err + return m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("data", string(dataJSON)).Error +} + +func (m *KillaraCustomerTokenModel) UpdateTokenExpiry(token string, expiry int64) error { + return m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("expiry", expiry).Error +} + +func (m *KillaraCustomerTokenModel) UpdateTokenCustomerID(token string, customerID uint64) error { + return m.db.Model(&KillaraCustomerToken{}).Where("token = ?", token).Update("customer_id", customerID).Error } -// DeleteToken deletes a token record func (m *KillaraCustomerTokenModel) DeleteToken(token string) error { err := m.db.Where("token = ?", token).Delete(&KillaraCustomerToken{}).Error if err == gorm.ErrRecordNotFound { @@ -67,90 +85,120 @@ func (m *KillaraCustomerTokenModel) DeleteToken(token string) error { return err } -// GetToken retrieves a token record by token value func (m *KillaraCustomerTokenModel) GetToken(token string) (*KillaraCustomerToken, error) { - var record KillaraCustomerToken - err := m.db.Where("token = ?", token).First(&record).Error + var tokenData KillaraCustomerToken + err := m.db.Where("token = ?", token).First(&tokenData).Error if err == gorm.ErrRecordNotFound { return nil, nil } - return &record, err + return &tokenData, err } -// CheckToken checks if a token is valid +// PHP 旧的代码 // func (m *KillaraCustomerTokenModel) CheckToken(token string) (*KillaraCustomerToken, error) { -// var record KillaraCustomerToken -// err := m.db.Where("token = ?", token).First(&record).Error +// tokenData, err := m.GetToken(token) // if err != nil { +// if errors.Is(err, gorm.ErrRecordNotFound) { +// return nil, nil +// } // return nil, err // } -// if record.Expiry == nil || record.Expiry.Before(time.Now()) { -// m.DeleteToken(token) -// return nil, ErrTokenExpired +// if *tokenData.Expiry > time.Now().Unix() { +// return tokenData, nil // } -// return &record, nil +// // 过期则删除 token +// m.DeleteToken(token) +// return nil, nil // } -// ClearDuplicateToken clears duplicate tokens for a customer_id -func (m *KillaraCustomerTokenModel) ClearDuplicateToken(customerID uint64, currentToken string, platform int64) error { - tokens := []KillaraCustomerToken{} - err := m.db.Where("customer_id = ? AND platform = ?", customerID, platform).Find(&tokens).Error - if err != nil { - return err - } - - for _, token := range tokens { - if *token.Token != currentToken { - m.UpdateTokenCustomerID(*token.Token, 0) +func (m *KillaraCustomerTokenModel) CheckToken(token string) (*KillaraCustomerToken, error) { + var resultToken *KillaraCustomerToken + err := m.db.Model(&KillaraCustomerToken{}).Transaction(func(tx *gorm.DB) error { + // 查找 Token 记录 + var token KillaraCustomerToken + err := tx.Where("token = ?", token).First(&token).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil + } + tx.Rollback() // 发生错误,回滚事务 + return err } - } - return nil -} + // 判断 Token 是否过期 + if *token.Expiry <= time.Now().Unix() { + // 过期则删除 Token + err = tx.Delete(&token).Error + if err != nil { + tx.Rollback() // 删除错误,回滚事务 + return err + } + } -// GetTokenByCustomerID retrieves the token value for a customer_id -func (m *KillaraCustomerTokenModel) GetTokenByCustomerID(customerID uint64) (string, error) { - var record KillaraCustomerToken - err := m.db.Select("token").Where("customer_id = ?", customerID).First(&record).Error - return *record.Token, err -} + resultToken = &token + return tx.Commit().Error // 提交事务 + }) -// GetTokenDataByCustomerID retrieves the token data for a customer_id -func (m *KillaraCustomerTokenModel) GetTokenDataByCustomerID(customerID uint64) (map[string]interface{}, error) { - var record KillaraCustomerToken - err := m.db.Select("data").Where("customer_id = ?", customerID).First(&record).Error if err != nil { return nil, err } + return resultToken, nil +} + +func (m *KillaraCustomerTokenModel) ClearDuplicateToken(customerID uint64, currentToken string, platform int) error { + + return m.db.Model(&KillaraCustomerToken{}).Transaction(func(tx *gorm.DB) error { + var tokens []KillaraCustomerToken + err := tx.Where("customer_id = ? AND platform = ?", customerID, platform).Find(&tokens).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Println("当前的token, 自身都不存在, 疑似出了什么错误1") + return nil + } + tx.Rollback() // 发生错误,回滚事务 + return err + } + + for _, token := range tokens { + if *token.Token != currentToken { + // err := tx.Delete(token).Error todo: 不太明白php为什么不删除token, 难道用来链路跟踪? 但是客户端id也被更新了, 没有存在的意义了 + err := tx.Where("token = ?", token).Update("customer_id", 0).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fmt.Errorf("tokens 查询出来, 自身都不存在, 疑似出了什么错误2") + } + tx.Rollback() // 发生错误,回滚事务 + return err + } + } + } + + return tx.Commit().Error + }) +} + +func (m *KillaraCustomerTokenModel) GetTokenByCustomerID(customerID uint64) (*string, error) { + var token KillaraCustomerToken + err := m.db.Select("token").Where("customer_id = ?", customerID).First(&token).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return token.Token, err +} + +func (m *KillaraCustomerTokenModel) GetTokenDataByCustomerID(customerID uint64) (map[string]interface{}, error) { + var token KillaraCustomerToken + err := m.db.Select("data").Where("customer_id = ?", customerID).First(&token).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, err + } var data map[string]interface{} - if record.Data != nil { - err = json.Unmarshal([]byte(*record.Data), &data) - if err != nil { - return nil, err - } - } - - return data, nil + err = json.Unmarshal([]byte(*token.Data), &data) + return data, err } - -func nilStringPtr(s string) *string { - if s == "" { - return nil - } - return &s -} - -func nilTimePtr(t time.Time) *time.Time { - if t.IsZero() { - return nil - } - return &t -} - -var ( - ErrInvalidTokenValue = errors.New("invalid token value") - ErrTokenExpired = errors.New("token has expired") -) diff --git a/php_model/Token.php b/php_model/Token.php index 710141b..60ebf11 100644 --- a/php_model/Token.php +++ b/php_model/Token.php @@ -41,7 +41,7 @@ class Model_Customer_Token extends \application\Model\Base\BaseModel if (!empty($data['customer_id']) && !empty($data['platform'])) { $this->db->query('DELETE FROM ' . $this->_customerTokenTable . ' WHERE customer_id = ' - . $this->db->quote($data['customer_id']) . ' AND platform = ' . $this->db->quote($data['platform'])); + . $data['customer_id'] . ' AND platform = ' . $data['platform']); } $this->db->insert($this->_customerTokenTable, $data); @@ -128,7 +128,7 @@ class Model_Customer_Token extends \application\Model\Base\BaseModel { return $this->db->fetchRow('SELECT * FROM ' . $this->_customerTokenTable - . ' WHERE token = ' . $this->db->quote($token)); + . ' WHERE token = ' . $token); } @@ -143,7 +143,7 @@ class Model_Customer_Token extends \application\Model\Base\BaseModel { $result = $this->db->fetchRow('SELECT * FROM ' . $this->_customerTokenTable - . ' WHERE token = ' . $this->db->quote($token)); + . ' WHERE token = ' . $token); if ($result) { if ($result['expiry'] > time()) { @@ -170,7 +170,7 @@ class Model_Customer_Token extends \application\Model\Base\BaseModel public function clearDuplicateToken($customer_id, $current_token, $platform = 1) { $results = $this->db->fetchAll('SELECT * FROM ' . $this->_customerTokenTable - . ' WHERE customer_id = ' . $this->db->quote($customer_id) . 'AND platform = ' . $this->db->quote($platform)); + . ' WHERE customer_id = ' . $customer_id . 'AND platform = ' . $platform); foreach ($results as $result) { if ($result['token'] != $current_token) { @@ -184,13 +184,13 @@ class Model_Customer_Token extends \application\Model\Base\BaseModel public function getTokenByCustomerId($customer_id) { return $this->db->fetchOne('SELECT token FROM ' . $this->_customerTokenTable - . ' WHERE customer_id = ' . $this->db->quote($customer_id)); + . ' WHERE customer_id = ' . $customer_id); } public function getTokenDataByCustomerId($customer_id) { $token_data = $this->db->fetchOne('SELECT data FROM ' . $this->_customerTokenTable - . ' WHERE customer_id = ' . $this->db->quote($customer_id)); + . ' WHERE customer_id = ' . $customer_id); return json_decode($token_data, true); } diff --git a/utils/auth/auth_test.go b/utils/auth/auth_test.go index c4c4a1b..551c820 100644 --- a/utils/auth/auth_test.go +++ b/utils/auth/auth_test.go @@ -19,7 +19,7 @@ func TestSignTokenAndParseToken(t *testing.T) { vm := &VestMoreClaims{ RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(time.Now()), - ExpiresAt: jwt.NewNumericDate(time.Now().UTC().Add(1 * time.Hour)), // 设置过期时间为当前时间加24小时 + ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)), // 设置过期时间为当前时间加24小时 Issuer: "vermore", }, }