refactor: 文件行数超标拆解(Service + Controller 9/16 完成)
- Service 层:energy_service → energize/operations/admin/query 四文件 - Service 层:post_service → helpers/audit + 核心 CRUD 保留 - Service 层:favorite_service → items + 核心文件夹操作保留 - Service 层:auth_service → password + 核心注册/登录保留 - Service 层:notification_service → notify + 核心列表/已读保留 - Service 层:audit_service → review + 核心列表/详情保留 - Controller 层:studio_controller → page/write/api/post_api/action 五文件 - Controller 层:post_controller → page/api/upload 三文件 - Controller 层:comment_controller → list/write/action/upload 四文件 - 清理未使用导入(notification_service.go 移除 fmt)
This commit is contained in:
@ -12,7 +12,6 @@ import (
|
||||
"metazone.cc/metalab/internal/session"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AuthService 认证业务逻辑
|
||||
@ -28,31 +27,9 @@ func NewAuthService(userRepo userAuthStore, sm *session.Manager, cfg *config.Con
|
||||
return &AuthService{userRepo: userRepo, sessionManager: sm, cfg: cfg, siteSettings: siteSettings}
|
||||
}
|
||||
|
||||
var pwLetter = regexp.MustCompile(`[a-zA-Z]`)
|
||||
var pwDigit = regexp.MustCompile(`\d`)
|
||||
|
||||
// usernamePattern 用户名合法字符:中文、英文大小写、数字、下划线、连字符
|
||||
var usernamePattern = regexp.MustCompile(`^[\p{Han}a-zA-Z0-9_-]+$`)
|
||||
|
||||
// dummyHash 防时序攻击:当用户不存在时,仍对虚拟哈希执行完整的 bcrypt 比对
|
||||
var dummyHash []byte
|
||||
|
||||
func init() {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte("metazone-dummy-hash-2026"), 12)
|
||||
if err != nil {
|
||||
panic("failed to generate bcrypt dummy hash: " + err.Error())
|
||||
}
|
||||
dummyHash = hash
|
||||
}
|
||||
|
||||
// validatePassword 密码强度:至少 8 位 + 包含字母 + 包含数字
|
||||
func validatePassword(pw string) error {
|
||||
if len(pw) < 8 || !pwLetter.MatchString(pw) || !pwDigit.MatchString(pw) {
|
||||
return common.ErrWeakPassword
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsRegistrationEnabled 检查是否允许新用户注册
|
||||
func (s *AuthService) IsRegistrationEnabled() bool {
|
||||
return s.siteSettings.IsRegistrationEnabled()
|
||||
@ -164,35 +141,6 @@ func (s *AuthService) Login(req model.LoginRequest, loginIP string) (*model.User
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// ConfirmRestore 二次确认恢复已注销账号
|
||||
func (s *AuthService) ConfirmRestore(req model.LoginRequest, loginIP string) (*model.User, error) {
|
||||
user, err := s.userRepo.FindByEmail(req.Email)
|
||||
if err != nil {
|
||||
_ = bcrypt.CompareHashAndPassword(dummyHash, []byte(req.Password))
|
||||
return nil, common.ErrInvalidCred
|
||||
}
|
||||
|
||||
if user.Status != model.StatusDeleted {
|
||||
return nil, common.ErrUserNotFound
|
||||
}
|
||||
|
||||
if bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)) != nil {
|
||||
return nil, common.ErrInvalidCred
|
||||
}
|
||||
|
||||
// 恢复账号
|
||||
user.Status = model.StatusActive
|
||||
user.DeletedAt = gorm.DeletedAt{}
|
||||
now := time.Now()
|
||||
user.LastLoginIP = loginIP
|
||||
user.LastLoginAt = &now
|
||||
if err := s.userRepo.Update(user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// CheckEmail 检查邮箱是否已被注册
|
||||
func (s *AuthService) CheckEmail(email string) (bool, error) {
|
||||
return s.userRepo.ExistsByEmail(email)
|
||||
@ -203,71 +151,6 @@ func (s *AuthService) GetProfile(userID uint) (*model.User, error) {
|
||||
return s.userRepo.FindByID(userID)
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
// 流程:验证当前密码 → 校验新密码强度 → 哈希 → 更新 → 删除所有 session(强制重新登录)
|
||||
func (s *AuthService) ChangePassword(userID uint, currentPassword, newPassword string) error {
|
||||
user, err := s.userRepo.FindByID(userID)
|
||||
if err != nil {
|
||||
return common.ErrUserNotFound
|
||||
}
|
||||
|
||||
if bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(currentPassword)) != nil {
|
||||
return common.ErrIncorrectPassword
|
||||
}
|
||||
|
||||
if err := validatePassword(newPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hash, err := common.HashPassword(newPassword, s.cfg.Bcrypt.Cost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.PasswordHash = hash
|
||||
if err := s.userRepo.Update(user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除所有 session,强制所有设备重新登录
|
||||
return s.invalidateSessions(userID)
|
||||
}
|
||||
|
||||
// DeleteAccount 用户自主注销
|
||||
func (s *AuthService) DeleteAccount(userID uint, password, reason string) error {
|
||||
user, err := s.userRepo.FindByID(userID)
|
||||
if err != nil {
|
||||
return common.ErrUserNotFound
|
||||
}
|
||||
|
||||
if user.Role == model.RoleOwner {
|
||||
return common.ErrOwnerCannotDelete
|
||||
}
|
||||
|
||||
if bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)) != nil {
|
||||
return common.ErrIncorrectPassword
|
||||
}
|
||||
|
||||
user.Status = model.StatusDeleted
|
||||
user.DeleteReason = reason
|
||||
|
||||
if err := s.userRepo.Update(user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.invalidateSessions(userID)
|
||||
}
|
||||
|
||||
// invalidateSessions 销毁某用户的所有 session(内部方法)
|
||||
func (s *AuthService) invalidateSessions(userID uint) error {
|
||||
return s.sessionManager.DestroyByUID(userID)
|
||||
}
|
||||
|
||||
// InvalidateSessions 公开方法:销毁用户所有 session(供 admin 等外部调用)
|
||||
func (s *AuthService) InvalidateSessions(userID uint) error {
|
||||
return s.sessionManager.DestroyByUID(userID)
|
||||
}
|
||||
|
||||
// UpdateProfile 修改个人资料
|
||||
func (s *AuthService) UpdateProfile(userID uint, username, bio string) error {
|
||||
user, err := s.userRepo.FindByID(userID)
|
||||
|
||||
Reference in New Issue
Block a user