package entities import ( "crypto/rand" "encoding/hex" "errors" "io" "net" "time" "github.com/google/uuid" "gorm.io/gorm" ) // ApiUserStatus API用户状态 const ( ApiUserStatusNormal = "normal" ApiUserStatusFrozen = "frozen" ) // ApiUser API用户(聚合根) type ApiUser struct { ID string `gorm:"primaryKey;type:varchar(64)" json:"id"` UserId string `gorm:"type:varchar(36);not null;uniqueIndex" json:"user_id"` AccessId string `gorm:"type:varchar(64);not null;uniqueIndex" json:"access_id"` SecretKey string `gorm:"type:varchar(128);not null" json:"secret_key"` Status string `gorm:"type:varchar(20);not null;default:'normal'" json:"status"` WhiteList []string `gorm:"type:json;serializer:json;default:'[]'" json:"white_list"` // 支持多个白名单 CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` } // IsWhiteListed 校验IP/域名是否在白名单 func (u *ApiUser) IsWhiteListed(target string) bool { for _, w := range u.WhiteList { if w == target { return true } } return false } // IsActive 是否可用 func (u *ApiUser) IsActive() bool { return u.Status == ApiUserStatusNormal } // IsFrozen 是否冻结 func (u *ApiUser) IsFrozen() bool { return u.Status == ApiUserStatusFrozen } // NewApiUser 工厂方法 func NewApiUser(userId string) (*ApiUser, error) { if userId == "" { return nil, errors.New("用户ID不能为空") } accessId, err := GenerateSecretId() if err != nil { return nil, err } secretKey, err := GenerateSecretKey() if err != nil { return nil, err } return &ApiUser{ ID: uuid.New().String(), UserId: userId, AccessId: accessId, SecretKey: secretKey, Status: ApiUserStatusNormal, WhiteList: []string{}, }, nil } // 领域行为 func (u *ApiUser) Freeze() { u.Status = ApiUserStatusFrozen } func (u *ApiUser) Unfreeze() { u.Status = ApiUserStatusNormal } func (u *ApiUser) UpdateWhiteList(list []string) { u.WhiteList = list } // AddToWhiteList 新增白名单项(防御性校验) func (u *ApiUser) AddToWhiteList(entry string) error { if len(u.WhiteList) >= 10 { return errors.New("白名单最多只能有10个") } if net.ParseIP(entry) == nil { return errors.New("非法IP") } for _, w := range u.WhiteList { if w == entry { return errors.New("白名单已存在") } } u.WhiteList = append(u.WhiteList, entry) return nil } // BeforeUpdate GORM钩子:更新前确保WhiteList不为nil func (u *ApiUser) BeforeUpdate(tx *gorm.DB) error { if u.WhiteList == nil { u.WhiteList = []string{} } return nil } // RemoveFromWhiteList 删除白名单项 func (u *ApiUser) RemoveFromWhiteList(entry string) error { newList := make([]string, 0, len(u.WhiteList)) for _, w := range u.WhiteList { if w != entry { newList = append(newList, w) } } if len(newList) == len(u.WhiteList) { return errors.New("白名单不存在") } u.WhiteList = newList return nil } // Validate 校验ApiUser聚合根的业务规则 func (u *ApiUser) Validate() error { if u.UserId == "" { return errors.New("用户ID不能为空") } if u.AccessId == "" { return errors.New("AccessId不能为空") } if u.SecretKey == "" { return errors.New("SecretKey不能为空") } switch u.Status { case ApiUserStatusNormal, ApiUserStatusFrozen: // ok default: return errors.New("无效的用户状态") } if len(u.WhiteList) > 10 { return errors.New("白名单最多只能有10个") } for _, ip := range u.WhiteList { if net.ParseIP(ip) == nil { return errors.New("白名单项必须为合法IP地址: " + ip) } } return nil } // 生成AES-128密钥的函数,符合市面规范 func GenerateSecretKey() (string, error) { key := make([]byte, 16) // 16字节密钥 _, err := io.ReadFull(rand.Reader, key) if err != nil { return "", err } return hex.EncodeToString(key), nil } func GenerateSecretId() (string, error) { // 创建一个字节数组,用于存储随机数据 bytes := make([]byte, 8) // 因为每个字节表示两个16进制字符 // 读取随机字节到数组中 _, err := rand.Read(bytes) if err != nil { return "", err } // 将字节数组转换为16进制字符串 return hex.EncodeToString(bytes), nil } // TableName 指定数据库表名 func (ApiUser) TableName() string { return "api_users" } // BeforeCreate GORM钩子:创建前自动生成UUID并确保WhiteList不为nil func (c *ApiUser) BeforeCreate(tx *gorm.DB) error { if c.ID == "" { c.ID = uuid.New().String() } if c.WhiteList == nil { c.WhiteList = []string{} } return nil }