package service import ( "carrotskin/internal/model" "carrotskin/internal/repository" "carrotskin/pkg/auth" "errors" "strings" "time" ) // RegisterUser 用户注册 func RegisterUser(jwtService *auth.JWTService, username, password, email, avatar string) (*model.User, string, error) { // 检查用户名是否已存在 existingUser, err := repository.FindUserByUsername(username) if err != nil { return nil, "", err } if existingUser != nil { return nil, "", errors.New("用户名已存在") } // 检查邮箱是否已存在 existingEmail, err := repository.FindUserByEmail(email) if err != nil { return nil, "", err } if existingEmail != nil { return nil, "", errors.New("邮箱已被注册") } // 加密密码 hashedPassword, err := auth.HashPassword(password) if err != nil { return nil, "", errors.New("密码加密失败") } // 确定头像URL:优先使用用户提供的头像,否则使用默认头像 avatarURL := avatar if avatarURL == "" { avatarURL = getDefaultAvatar() } // 创建用户 user := &model.User{ Username: username, Password: hashedPassword, Email: email, Avatar: avatarURL, Role: "user", Status: 1, Points: 0, // 初始积分可以从配置读取 } if err := repository.CreateUser(user); err != nil { return nil, "", err } // 生成JWT Token token, err := jwtService.GenerateToken(user.ID, user.Username, user.Role) if err != nil { return nil, "", errors.New("生成Token失败") } // TODO: 添加注册奖励积分 return user, token, nil } // LoginUser 用户登录(支持用户名或邮箱登录) func LoginUser(jwtService *auth.JWTService, usernameOrEmail, password, ipAddress, userAgent string) (*model.User, string, error) { // 查找用户:判断是用户名还是邮箱 var user *model.User var err error if strings.Contains(usernameOrEmail, "@") { // 包含@符号,认为是邮箱 user, err = repository.FindUserByEmail(usernameOrEmail) } else { // 否则认为是用户名 user, err = repository.FindUserByUsername(usernameOrEmail) } if err != nil { return nil, "", err } if user == nil { // 记录失败日志 logFailedLogin(0, ipAddress, userAgent, "用户不存在") return nil, "", errors.New("用户名/邮箱或密码错误") } // 检查用户状态 if user.Status != 1 { logFailedLogin(user.ID, ipAddress, userAgent, "账号已被禁用") return nil, "", errors.New("账号已被禁用") } // 验证密码 if !auth.CheckPassword(user.Password, password) { logFailedLogin(user.ID, ipAddress, userAgent, "密码错误") return nil, "", errors.New("用户名/邮箱或密码错误") } // 生成JWT Token token, err := jwtService.GenerateToken(user.ID, user.Username, user.Role) if err != nil { return nil, "", errors.New("生成Token失败") } // 更新最后登录时间 now := time.Now() user.LastLoginAt = &now _ = repository.UpdateUserFields(user.ID, map[string]interface{}{ "last_login_at": now, }) // 记录成功登录日志 logSuccessLogin(user.ID, ipAddress, userAgent) return user, token, nil } // GetUserByID 根据ID获取用户 func GetUserByID(id int64) (*model.User, error) { return repository.FindUserByID(id) } // UpdateUserInfo 更新用户信息 func UpdateUserInfo(user *model.User) error { return repository.UpdateUser(user) } // UpdateUserAvatar 更新用户头像 func UpdateUserAvatar(userID int64, avatarURL string) error { return repository.UpdateUserFields(userID, map[string]interface{}{ "avatar": avatarURL, }) } // ChangeUserPassword 修改密码 func ChangeUserPassword(userID int64, oldPassword, newPassword string) error { // 获取用户 user, err := repository.FindUserByID(userID) if err != nil { return errors.New("用户不存在") } // 验证旧密码 if !auth.CheckPassword(user.Password, oldPassword) { return errors.New("原密码错误") } // 加密新密码 hashedPassword, err := auth.HashPassword(newPassword) if err != nil { return errors.New("密码加密失败") } // 更新密码 return repository.UpdateUserFields(userID, map[string]interface{}{ "password": hashedPassword, }) } // ResetUserPassword 重置密码(通过邮箱) func ResetUserPassword(email, newPassword string) error { // 查找用户 user, err := repository.FindUserByEmail(email) if err != nil { return errors.New("用户不存在") } // 加密新密码 hashedPassword, err := auth.HashPassword(newPassword) if err != nil { return errors.New("密码加密失败") } // 更新密码 return repository.UpdateUserFields(user.ID, map[string]interface{}{ "password": hashedPassword, }) } // ChangeUserEmail 更换邮箱 func ChangeUserEmail(userID int64, newEmail string) error { // 检查新邮箱是否已被使用 existingUser, err := repository.FindUserByEmail(newEmail) if err != nil { return err } if existingUser != nil && existingUser.ID != userID { return errors.New("邮箱已被其他用户使用") } // 更新邮箱 return repository.UpdateUserFields(userID, map[string]interface{}{ "email": newEmail, }) } // logSuccessLogin 记录成功登录 func logSuccessLogin(userID int64, ipAddress, userAgent string) { log := &model.UserLoginLog{ UserID: userID, IPAddress: ipAddress, UserAgent: userAgent, LoginMethod: "PASSWORD", IsSuccess: true, } _ = repository.CreateLoginLog(log) } // logFailedLogin 记录失败登录 func logFailedLogin(userID int64, ipAddress, userAgent, reason string) { log := &model.UserLoginLog{ UserID: userID, IPAddress: ipAddress, UserAgent: userAgent, LoginMethod: "PASSWORD", IsSuccess: false, FailureReason: reason, } _ = repository.CreateLoginLog(log) } // getDefaultAvatar 获取默认头像URL func getDefaultAvatar() string { // 如果数据库中不存在默认头像配置,返回错误信息 const log = "数据库中不存在默认头像配置" // 尝试从数据库读取配置 config, err := repository.GetSystemConfigByKey("default_avatar") if err != nil || config == nil { return log } return config.Value } func GetUserByEmail(email string) (*model.User, error) { user, err := repository.FindUserByEmail(email) if err != nil { return nil, errors.New("邮箱查找失败") } return user, nil }