- 全局替换 ApiKey → APIKey(类型、字段、方法、变量) - 修复所有 initialism 命名(API, SMTP, HTML, URL 等) - 添加所有缺失的包注释 - 修复导出符号的注释格式 主要修改: - ApiKey → APIKey(所有出现的地方) - ApiKeyID → APIKeyID - ApiKeyIDs → APIKeyIDs - TestSmtpConnection → TestSMTPConnection - HtmlURL → HTMLURL - 添加 20+ 个包注释 - 修复 10+ 个导出符号注释格式 验证结果: - ✓ golangci-lint: 0 issues - ✓ 单元测试: 通过 - ✓ 集成测试: 通过
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package service
|
|
|
|
import (
|
|
"time"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type User struct {
|
|
ID int64
|
|
Email string
|
|
Username string
|
|
Notes string
|
|
PasswordHash string
|
|
Role string
|
|
Balance float64
|
|
Concurrency int
|
|
Status string
|
|
AllowedGroups []int64
|
|
TokenVersion int64 // Incremented on password change to invalidate existing tokens
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
|
|
APIKeys []APIKey
|
|
Subscriptions []UserSubscription
|
|
}
|
|
|
|
func (u *User) IsAdmin() bool {
|
|
return u.Role == RoleAdmin
|
|
}
|
|
|
|
func (u *User) IsActive() bool {
|
|
return u.Status == StatusActive
|
|
}
|
|
|
|
// CanBindGroup checks whether a user can bind to a given group.
|
|
// For standard groups:
|
|
// - If AllowedGroups is non-empty, only allow binding to IDs in that list.
|
|
// - If AllowedGroups is empty (nil or length 0), allow binding to any non-exclusive group.
|
|
func (u *User) CanBindGroup(groupID int64, isExclusive bool) bool {
|
|
if len(u.AllowedGroups) > 0 {
|
|
for _, id := range u.AllowedGroups {
|
|
if id == groupID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
return !isExclusive
|
|
}
|
|
|
|
func (u *User) SetPassword(password string) error {
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u.PasswordHash = string(hash)
|
|
return nil
|
|
}
|
|
|
|
func (u *User) CheckPassword(password string) bool {
|
|
return bcrypt.CompareHashAndPassword([]byte(u.PasswordHash), []byte(password)) == nil
|
|
}
|