package entities import ( "crypto/sha256" "encoding/hex" "fmt" "regexp" "time" "github.com/google/uuid" "gorm.io/gorm" ) // UserType 用户类型枚举 type UserType string const ( UserTypeNormal UserType = "user" // 普通用户 UserTypeAdmin UserType = "admin" // 管理员 ) // User 用户聚合根 // 系统用户的核心信息,提供基础的账户管理功能 // 支持手机号登录,密码加密存储,实现Entity接口便于统一管理 type User struct { // 基础标识 ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"用户唯一标识"` Phone string `gorm:"uniqueIndex;type:varchar(20);not null" json:"phone" comment:"手机号码(登录账号)"` Password string `gorm:"type:varchar(255);not null" json:"-" comment:"登录密码(加密存储,不返回前端)"` // 用户类型和基本信息 UserType string `gorm:"type:varchar(20);not null;default:'user'" json:"user_type" comment:"用户类型(user/admin)"` Username string `gorm:"type:varchar(100)" json:"username" comment:"用户名(管理员专用)"` // 管理员特有字段 Active bool `gorm:"default:true" json:"is_active" comment:"账户是否激活"` IsCertified bool `gorm:"default:false" json:"is_certified" comment:"是否完成认证"` LastLoginAt *time.Time `json:"last_login_at" comment:"最后登录时间"` LoginCount int `gorm:"default:0" json:"login_count" comment:"登录次数统计"` Permissions string `gorm:"type:text" json:"permissions" comment:"权限列表(JSON格式存储)"` // 时间戳字段 CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` // 关联关系 EnterpriseInfo *EnterpriseInfo `gorm:"foreignKey:UserID" json:"enterprise_info,omitempty" comment:"企业信息(认证后获得)"` // 领域事件 (不持久化) domainEvents []interface{} `gorm:"-" json:"-"` } // BeforeCreate GORM钩子:创建前自动生成UUID func (u *User) BeforeCreate(tx *gorm.DB) error { if u.ID == "" { u.ID = uuid.New().String() } return nil } // 实现 Entity 接口 - 提供统一的实体管理接口 // GetID 获取实体唯一标识 func (u *User) GetID() string { return u.ID } // GetCreatedAt 获取创建时间 func (u *User) GetCreatedAt() time.Time { return u.CreatedAt } // GetUpdatedAt 获取更新时间 func (u *User) GetUpdatedAt() time.Time { return u.UpdatedAt } // Validate 验证用户信息 // 检查用户必填字段是否完整,确保数据的有效性 func (u *User) Validate() error { if u.Phone == "" { return NewValidationError("手机号不能为空") } if u.Password == "" { return NewValidationError("密码不能为空") } // 验证手机号格式 if !u.IsValidPhone() { return NewValidationError("手机号格式无效") } return nil } // CompleteCertification 完成认证 func (u *User) CompleteCertification() error { u.IsCertified = true return nil } // ================ 企业信息管理方法 ================ // CreateEnterpriseInfo 创建企业信息 func (u *User) CreateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress string) error { // 检查是否已有企业信息 if u.EnterpriseInfo != nil { return fmt.Errorf("用户已有企业信息") } // 创建企业信息实体 enterpriseInfo, err := NewEnterpriseInfo(u.ID, companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress) if err != nil { return fmt.Errorf("创建企业信息失败: %w", err) } // 设置关联关系 u.EnterpriseInfo = enterpriseInfo // 添加领域事件 u.addDomainEvent(&UserEnterpriseInfoCreatedEvent{ UserID: u.ID, EnterpriseInfoID: enterpriseInfo.ID, CompanyName: companyName, UnifiedSocialCode: unifiedSocialCode, CreatedAt: time.Now(), }) return nil } // UpdateEnterpriseInfo 更新企业信息 func (u *User) UpdateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress string) error { // 检查是否有企业信息 if u.EnterpriseInfo == nil { return fmt.Errorf("用户暂无企业信息") } // 记录原始值用于事件 oldCompanyName := u.EnterpriseInfo.CompanyName oldUnifiedSocialCode := u.EnterpriseInfo.UnifiedSocialCode // 更新企业信息 err := u.EnterpriseInfo.UpdateEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress) if err != nil { return err } // 添加领域事件 u.addDomainEvent(&UserEnterpriseInfoUpdatedEvent{ UserID: u.ID, EnterpriseInfoID: u.EnterpriseInfo.ID, OldCompanyName: oldCompanyName, NewCompanyName: companyName, OldUnifiedSocialCode: oldUnifiedSocialCode, NewUnifiedSocialCode: unifiedSocialCode, UpdatedAt: time.Now(), }) return nil } // GetEnterpriseInfo 获取企业信息 func (u *User) GetEnterpriseInfo() *EnterpriseInfo { return u.EnterpriseInfo } // HasEnterpriseInfo 检查是否有企业信息 func (u *User) HasEnterpriseInfo() bool { return u.EnterpriseInfo != nil } // RemoveEnterpriseInfo 移除企业信息 func (u *User) RemoveEnterpriseInfo() error { if u.EnterpriseInfo == nil { return fmt.Errorf("用户暂无企业信息") } enterpriseInfoID := u.EnterpriseInfo.ID u.EnterpriseInfo = nil // 添加领域事件 u.addDomainEvent(&UserEnterpriseInfoRemovedEvent{ UserID: u.ID, EnterpriseInfoID: enterpriseInfoID, RemovedAt: time.Now(), }) return nil } // ValidateEnterpriseInfo 验证企业信息 func (u *User) ValidateEnterpriseInfo() error { if u.EnterpriseInfo == nil { return fmt.Errorf("用户暂无企业信息") } return u.EnterpriseInfo.ValidateBusinessRules() } // ================ 聚合根核心方法 ================ // Register 用户注册 func (u *User) Register() error { // 验证用户信息 if err := u.Validate(); err != nil { return fmt.Errorf("用户信息验证失败: %w", err) } // 添加领域事件 u.addDomainEvent(&UserRegisteredEvent{ UserID: u.ID, Phone: u.Phone, UserType: u.UserType, CreatedAt: time.Now(), }) return nil } // Login 用户登录 func (u *User) Login(ipAddress, userAgent string) error { // 检查用户是否可以登录 if !u.CanLogin() { return fmt.Errorf("用户无法登录") } // 更新登录信息 u.UpdateLastLoginAt() u.IncrementLoginCount() // 添加领域事件 u.addDomainEvent(&UserLoggedInEvent{ UserID: u.ID, Phone: u.Phone, IPAddress: ipAddress, UserAgent: userAgent, LoginAt: time.Now(), }) return nil } // ChangePassword 修改密码 func (u *User) ChangePassword(oldPassword, newPassword, confirmPassword string) error { // 验证旧密码 if !u.CheckPassword(oldPassword) { return fmt.Errorf("原密码错误") } // 验证新密码 if newPassword != confirmPassword { return fmt.Errorf("两次输入的密码不一致") } // 设置新密码 if err := u.SetPassword(newPassword); err != nil { return fmt.Errorf("设置新密码失败: %w", err) } // 添加领域事件 u.addDomainEvent(&UserPasswordChangedEvent{ UserID: u.ID, Phone: u.Phone, ChangedAt: time.Now(), }) return nil } // ActivateUser 激活用户 func (u *User) ActivateUser() error { if u.Active { return fmt.Errorf("用户已经是激活状态") } u.Activate() // 添加领域事件 u.addDomainEvent(&UserActivatedEvent{ UserID: u.ID, Phone: u.Phone, ActivatedAt: time.Now(), }) return nil } // DeactivateUser 停用用户 func (u *User) DeactivateUser() error { if !u.Active { return fmt.Errorf("用户已经是停用状态") } u.Deactivate() // 添加领域事件 u.addDomainEvent(&UserDeactivatedEvent{ UserID: u.ID, Phone: u.Phone, DeactivatedAt: time.Now(), }) return nil } // ================ 业务规则验证 ================ // ValidateBusinessRules 验证业务规则 func (u *User) ValidateBusinessRules() error { // 1. 基础字段验证 if err := u.validateBasicFields(); err != nil { return fmt.Errorf("基础字段验证失败: %w", err) } // 2. 业务规则验证 if err := u.validateBusinessLogic(); err != nil { return fmt.Errorf("业务规则验证失败: %w", err) } // 3. 状态一致性验证 if err := u.validateStateConsistency(); err != nil { return fmt.Errorf("状态一致性验证失败: %w", err) } return nil } // validateBasicFields 验证基础字段 func (u *User) validateBasicFields() error { if u.Phone == "" { return fmt.Errorf("手机号不能为空") } if u.Password == "" { return fmt.Errorf("密码不能为空") } // 验证手机号格式 if !u.IsValidPhone() { return fmt.Errorf("手机号格式无效") } // 不对加密后的hash做长度校验 return nil } // validateBusinessLogic 验证业务逻辑 func (u *User) validateBusinessLogic() error { // 管理员用户必须有用户名 // if u.IsAdmin() && u.Username == "" { // return fmt.Errorf("管理员用户必须有用户名") // } // // 普通用户不能有用户名 // if u.IsNormalUser() && u.Username != "" { // return fmt.Errorf("普通用户不能有用户名") // } return nil } // validateStateConsistency 验证状态一致性 func (u *User) validateStateConsistency() error { // 如果用户被删除,不能是激活状态 if u.IsDeleted() && u.Active { return fmt.Errorf("已删除用户不能是激活状态") } return nil } // ================ 领域事件管理 ================ // addDomainEvent 添加领域事件 func (u *User) addDomainEvent(event interface{}) { if u.domainEvents == nil { u.domainEvents = make([]interface{}, 0) } u.domainEvents = append(u.domainEvents, event) } // GetDomainEvents 获取领域事件 func (u *User) GetDomainEvents() []interface{} { return u.domainEvents } // ClearDomainEvents 清除领域事件 func (u *User) ClearDomainEvents() { u.domainEvents = make([]interface{}, 0) } // ================ 业务方法 ================ // IsAdmin 检查是否为管理员 func (u *User) IsAdmin() bool { return u.UserType == string(UserTypeAdmin) } // IsNormalUser 检查是否为普通用户 func (u *User) IsNormalUser() bool { return u.UserType == string(UserTypeNormal) } // SetUserType 设置用户类型 func (u *User) SetUserType(userType UserType) { u.UserType = string(userType) } // UpdateLastLoginAt 更新最后登录时间 func (u *User) UpdateLastLoginAt() { now := time.Now() u.LastLoginAt = &now } // IncrementLoginCount 增加登录次数 func (u *User) IncrementLoginCount() { u.LoginCount++ } // Activate 激活用户账户 func (u *User) Activate() { u.Active = true } // Deactivate 停用用户账户 func (u *User) Deactivate() { u.Active = false } // CheckPassword 验证密码是否正确 func (u *User) CheckPassword(password string) bool { return u.Password == hashPassword(password) } // SetPassword 设置密码(用于注册或重置密码) func (u *User) SetPassword(password string) error { // 只对明文做强度校验 if err := u.validatePasswordStrength(password); err != nil { return err } u.Password = hashPassword(password) return nil } // ResetPassword 重置密码(忘记密码时使用) func (u *User) ResetPassword(newPassword, confirmPassword string) error { if newPassword != confirmPassword { return NewValidationError("新密码和确认新密码不匹配") } if err := u.validatePasswordStrength(newPassword); err != nil { return err } u.Password = hashPassword(newPassword) return nil } // CanLogin 检查用户是否可以登录 func (u *User) CanLogin() bool { // 检查用户是否被删除 if !u.DeletedAt.Time.IsZero() { return false } // 检查必要字段是否存在 if u.Phone == "" || u.Password == "" { return false } // 如果是管理员,检查是否激活 if u.IsAdmin() && !u.Active { return false } return true } // IsActive 检查用户是否处于活跃状态 func (u *User) IsActive() bool { return u.DeletedAt.Time.IsZero() } // IsDeleted 检查用户是否已被删除 func (u *User) IsDeleted() bool { return !u.DeletedAt.Time.IsZero() } // ================ 手机号相关方法 ================ // IsValidPhone 验证手机号格式 func (u *User) IsValidPhone() bool { return IsValidPhoneFormat(u.Phone) } // SetPhone 设置手机号 func (u *User) SetPhone(phone string) error { if !IsValidPhoneFormat(phone) { return NewValidationError("手机号格式无效") } u.Phone = phone return nil } // GetMaskedPhone 获取脱敏的手机号 func (u *User) GetMaskedPhone() string { if len(u.Phone) < 7 { return u.Phone } return u.Phone[:3] + "****" + u.Phone[len(u.Phone)-4:] } // ================ 私有方法 ================ // hashPassword 使用sha256+hex加密密码 func hashPassword(password string) string { h := sha256.New() h.Write([]byte(password)) return hex.EncodeToString(h.Sum(nil)) } // validatePasswordStrength 只对明文做长度/强度校验 func (u *User) validatePasswordStrength(password string) error { if len(password) < 6 { return NewValidationError("密码长度不能少于6位") } if len(password) > 20 { return NewValidationError("密码长度不能超过20位") } return nil } // IsValidPhoneFormat 验证手机号格式 func IsValidPhoneFormat(phone string) bool { pattern := `^1[3-9]\d{9}$` matched, _ := regexp.MatchString(pattern, phone) return matched } // NewUser 创建新用户 func NewUser(phone, password string) (*User, error) { user := &User{ Phone: phone, UserType: string(UserTypeNormal), // 默认为普通用户 Active: true, } if err := user.SetPassword(password); err != nil { return nil, err } return user, nil } // NewAdminUser 创建新管理员用户 func NewAdminUser(phone, password, username string) (*User, error) { user := &User{ Phone: phone, Username: username, UserType: string(UserTypeAdmin), Active: true, } if err := user.SetPassword(password); err != nil { return nil, err } return user, nil } // TableName 指定数据库表名 func (User) TableName() string { return "users" } // ================ 错误处理 ================ type ValidationError struct { Message string } func (e *ValidationError) Error() string { return e.Message } func NewValidationError(message string) *ValidationError { return &ValidationError{Message: message} } func IsValidationError(err error) bool { _, ok := err.(*ValidationError) return ok } // ================ 领域事件定义 ================ // UserRegisteredEvent 用户注册事件 type UserRegisteredEvent struct { UserID string `json:"user_id"` Phone string `json:"phone"` UserType string `json:"user_type"` CreatedAt time.Time `json:"created_at"` } // UserLoggedInEvent 用户登录事件 type UserLoggedInEvent struct { UserID string `json:"user_id"` Phone string `json:"phone"` IPAddress string `json:"ip_address"` UserAgent string `json:"user_agent"` LoginAt time.Time `json:"login_at"` } // UserPasswordChangedEvent 用户密码修改事件 type UserPasswordChangedEvent struct { UserID string `json:"user_id"` Phone string `json:"phone"` ChangedAt time.Time `json:"changed_at"` } // UserActivatedEvent 用户激活事件 type UserActivatedEvent struct { UserID string `json:"user_id"` Phone string `json:"phone"` ActivatedAt time.Time `json:"activated_at"` } // UserDeactivatedEvent 用户停用事件 type UserDeactivatedEvent struct { UserID string `json:"user_id"` Phone string `json:"phone"` DeactivatedAt time.Time `json:"deactivated_at"` } // UserEnterpriseInfoCreatedEvent 企业信息创建事件 type UserEnterpriseInfoCreatedEvent struct { UserID string `json:"user_id"` EnterpriseInfoID string `json:"enterprise_info_id"` CompanyName string `json:"company_name"` UnifiedSocialCode string `json:"unified_social_code"` CreatedAt time.Time `json:"created_at"` } // UserEnterpriseInfoUpdatedEvent 企业信息更新事件 type UserEnterpriseInfoUpdatedEvent struct { UserID string `json:"user_id"` EnterpriseInfoID string `json:"enterprise_info_id"` OldCompanyName string `json:"old_company_name"` NewCompanyName string `json:"new_company_name"` OldUnifiedSocialCode string `json:"old_unified_social_code"` NewUnifiedSocialCode string `json:"new_unified_social_code"` UpdatedAt time.Time `json:"updated_at"` } // UserEnterpriseInfoRemovedEvent 企业信息移除事件 type UserEnterpriseInfoRemovedEvent struct { UserID string `json:"user_id"` EnterpriseInfoID string `json:"enterprise_info_id"` RemovedAt time.Time `json:"removed_at"` }