首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloudnest/internal/domain/auth/entity"
|
||||
"cloudnest/internal/domain/auth/repository"
|
||||
"cloudnest/internal/pkg/crypto"
|
||||
"cloudnest/internal/pkg/errors"
|
||||
"cloudnest/internal/pkg/jwt"
|
||||
)
|
||||
|
||||
type EmailVerifier interface {
|
||||
VerifyCode(email, code string) bool
|
||||
}
|
||||
|
||||
type AuthService struct {
|
||||
userRepo repository.UserRepository
|
||||
emailService EmailVerifier
|
||||
jwtSecret string
|
||||
jwtExpires int
|
||||
}
|
||||
|
||||
func NewAuthService(userRepo repository.UserRepository, emailService EmailVerifier, jwtSecret string, jwtExpires int) *AuthService {
|
||||
return &AuthService{
|
||||
userRepo: userRepo,
|
||||
emailService: emailService,
|
||||
jwtSecret: jwtSecret,
|
||||
jwtExpires: jwtExpires,
|
||||
}
|
||||
}
|
||||
|
||||
func generateUserCode() string {
|
||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
b := make([]byte, 8)
|
||||
for i := range b {
|
||||
b[i] = charset[r.Intn(len(charset))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (s *AuthService) Register(username, password, email, nickname, emailCode string) error {
|
||||
existing, err := s.userRepo.FindByUsername(username)
|
||||
if err == nil && existing != nil {
|
||||
return errors.Conflict("用户名已存在")
|
||||
}
|
||||
|
||||
if email != "" {
|
||||
existing, err := s.userRepo.FindByEmail(email)
|
||||
if err == nil && existing != nil {
|
||||
return errors.Conflict("邮箱已被注册")
|
||||
}
|
||||
if emailCode == "" {
|
||||
return errors.BadRequest("邮箱验证码不能为空")
|
||||
}
|
||||
if !s.emailService.VerifyCode(email, emailCode) {
|
||||
return errors.BadRequest("邮箱验证码错误")
|
||||
}
|
||||
}
|
||||
|
||||
hashed, err := crypto.HashPassword(password)
|
||||
if err != nil {
|
||||
return errors.InternalError("密码加密失败", err)
|
||||
}
|
||||
|
||||
userCode := generateUserCode()
|
||||
for {
|
||||
existing, err := s.userRepo.FindByUserCode(userCode)
|
||||
if err != nil || existing == nil {
|
||||
break
|
||||
}
|
||||
userCode = generateUserCode()
|
||||
}
|
||||
|
||||
user := entity.NewUser(username, hashed, userCode, nickname)
|
||||
if email != "" {
|
||||
user.Email = email
|
||||
}
|
||||
return s.userRepo.Create(user)
|
||||
}
|
||||
|
||||
func (s *AuthService) Login(loginName, password string) (string, *entity.User, error) {
|
||||
var user *entity.User
|
||||
var err error
|
||||
|
||||
if strings.Contains(loginName, "@") {
|
||||
user, err = s.userRepo.FindByEmail(loginName)
|
||||
} else {
|
||||
user, err = s.userRepo.FindByUsername(loginName)
|
||||
}
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if !crypto.CheckPasswordHash(password, user.Password) {
|
||||
return "", nil, errors.Unauthorized("用户名或密码错误")
|
||||
}
|
||||
|
||||
expiresIn := time.Duration(s.jwtExpires) * time.Hour
|
||||
token, err := jwt.GenerateToken(user.ID, user.Username, user.UserCode, s.jwtSecret, expiresIn)
|
||||
return token, user, err
|
||||
}
|
||||
|
||||
func (s *AuthService) CheckStorageLimit(userCode string, fileSize int64) error {
|
||||
user, err := s.userRepo.FindByUserCode(userCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user.StorageUsed+fileSize > user.StorageLimit {
|
||||
return errors.BadRequest("存储空间不足,当前已使用 " + formatSize(user.StorageUsed) + ",限制 " + formatSize(user.StorageLimit))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AuthService) AddStorageUsed(userCode string, fileSize int64) error {
|
||||
return s.userRepo.UpdateStorageUsed(userCode, fileSize)
|
||||
}
|
||||
|
||||
func (s *AuthService) SubtractStorageUsed(userCode string, fileSize int64) error {
|
||||
return s.userRepo.UpdateStorageUsed(userCode, -fileSize)
|
||||
}
|
||||
|
||||
func (s *AuthService) UpdateProfile(userCode, email, phone, nickname string) error {
|
||||
return s.userRepo.UpdateProfile(userCode, email, phone, nickname)
|
||||
}
|
||||
|
||||
func (s *AuthService) ChangePassword(userCode, currentPassword, newPassword string) error {
|
||||
user, err := s.userRepo.FindByUserCode(userCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !crypto.CheckPasswordHash(currentPassword, user.Password) {
|
||||
return errors.Unauthorized("当前密码不正确")
|
||||
}
|
||||
hashed, err := crypto.HashPassword(newPassword)
|
||||
if err != nil {
|
||||
return errors.InternalError("密码加密失败", err)
|
||||
}
|
||||
return s.userRepo.UpdatePassword(userCode, hashed)
|
||||
}
|
||||
|
||||
func (s *AuthService) GetUserInfo(userCode string) (*entity.User, error) {
|
||||
return s.userRepo.FindByUserCode(userCode)
|
||||
}
|
||||
|
||||
func formatSize(bytes int64) string {
|
||||
if bytes < 1024 {
|
||||
return fmt.Sprintf("%d B", bytes)
|
||||
} else if bytes < 1024*1024 {
|
||||
return fmt.Sprintf("%.2f KB", float64(bytes)/1024)
|
||||
} else if bytes < 1024*1024*1024 {
|
||||
return fmt.Sprintf("%.2f MB", float64(bytes)/(1024*1024))
|
||||
}
|
||||
return fmt.Sprintf("%.2f GB", float64(bytes)/(1024*1024*1024))
|
||||
}
|
||||
Reference in New Issue
Block a user