fix: 离线证到期重签空邮箱撞唯一索引
复用 customer_id/同名客户,禁止重复插入空 email;重签前端带回原客户。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
bac72e6945
commit
f26e787cfc
4 files changed
+62
-24
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
"backend/internal/model"
|
||||
"backend/utils"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -85,34 +86,24 @@ func (s *OfflineIssuer) Issue(req dto.OfflineLicenseCreate) (*dto.OfflineLicense
|
||||
return nil, errors.New("客户不存在")
|
||||
}
|
||||
} else {
|
||||
email := strings.TrimSpace(req.Email)
|
||||
name := strings.TrimSpace(req.CustomerName)
|
||||
if name == "" {
|
||||
name = "离线客户"
|
||||
}
|
||||
if email != "" {
|
||||
err := s.db.Where("email = ?", email).First(&customer).Error
|
||||
if err != nil {
|
||||
customer = model.Customer{Name: name, Email: email, Status: 1}
|
||||
if err := s.db.Create(&customer).Error; err != nil {
|
||||
return nil, errors.New("创建客户失败")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
customer = model.Customer{Name: name, Email: "", Status: 1}
|
||||
if err := s.db.Create(&customer).Error; err != nil {
|
||||
return nil, errors.New("创建客户失败")
|
||||
}
|
||||
var err error
|
||||
customer, err = s.resolveOrCreateCustomer(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
exp := now.AddDate(0, 0, duration)
|
||||
claimEmail := strings.TrimSpace(req.Email)
|
||||
if claimEmail == "" && customer.Email != "" && !strings.HasSuffix(customer.Email, "@local.invalid") {
|
||||
claimEmail = customer.Email
|
||||
}
|
||||
claims := utils.OfflineLicenseClaims{
|
||||
V: 1,
|
||||
ProductCode: product.Code,
|
||||
DeviceID: deviceID,
|
||||
Email: strings.TrimSpace(req.Email),
|
||||
Email: claimEmail,
|
||||
PlanType: planType,
|
||||
IssuedAt: now.Unix(),
|
||||
ExpiresAt: exp.Unix(),
|
||||
@@ -175,3 +166,39 @@ func (s *OfflineIssuer) Issue(req dto.OfflineLicenseCreate) (*dto.OfflineLicense
|
||||
PublicKey: s.kp.OfflinePublicKeyHex(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// resolveOrCreateCustomer 解析或创建离线签发客户;禁止重复插入空邮箱(uniqueIndex) // Logan.Li
|
||||
func (s *OfflineIssuer) resolveOrCreateCustomer(req dto.OfflineLicenseCreate) (model.Customer, error) {
|
||||
email := strings.TrimSpace(req.Email)
|
||||
name := strings.TrimSpace(req.CustomerName)
|
||||
if name == "" {
|
||||
name = "离线客户"
|
||||
}
|
||||
|
||||
var customer model.Customer
|
||||
if email != "" {
|
||||
if err := s.db.Where("email = ?", email).First(&customer).Error; err == nil {
|
||||
return customer, nil
|
||||
}
|
||||
customer = model.Customer{Name: name, Email: email, Status: 1}
|
||||
if err := s.db.Create(&customer).Error; err != nil {
|
||||
// 并发下可能已被创建,再查一次 // Logan.Li
|
||||
if err2 := s.db.Where("email = ?", email).First(&customer).Error; err2 == nil {
|
||||
return customer, nil
|
||||
}
|
||||
return customer, errors.New("创建客户失败")
|
||||
}
|
||||
return customer, nil
|
||||
}
|
||||
|
||||
// 无邮箱:优先复用同名客户,避免空邮箱触发 UNIQUE 冲突 // Logan.Li
|
||||
if err := s.db.Where("name = ?", name).Order("id ASC").First(&customer).Error; err == nil {
|
||||
return customer, nil
|
||||
}
|
||||
placeholder := fmt.Sprintf("offline+%d@local.invalid", time.Now().UnixNano())
|
||||
customer = model.Customer{Name: name, Email: placeholder, Status: 1}
|
||||
if err := s.db.Create(&customer).Error; err != nil {
|
||||
return customer, errors.New("创建客户失败")
|
||||
}
|
||||
return customer, nil
|
||||
}
|
||||
Reference in new issue
Block a user