user.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package service
  2. import (
  3. "context"
  4. "github.com/go-nunu/nunu-layout-advanced/internal/model"
  5. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  6. "github.com/golang-jwt/jwt/v5"
  7. "github.com/pkg/errors"
  8. "golang.org/x/crypto/bcrypt"
  9. "time"
  10. )
  11. type RegisterRequest struct {
  12. Username string `json:"username" binding:"required"`
  13. Password string `json:"password" binding:"required"`
  14. Email string `json:"email" binding:"required,email"`
  15. }
  16. type LoginRequest struct {
  17. Username string `json:"username" binding:"required"`
  18. Password string `json:"password" binding:"required"`
  19. }
  20. type UpdateProfileRequest struct {
  21. Nickname string `json:"nickname"`
  22. Email string `json:"email" binding:"required,email"`
  23. Avatar string `json:"avatar"`
  24. }
  25. type ChangePasswordRequest struct {
  26. OldPassword string `json:"oldPassword" binding:"required"`
  27. NewPassword string `json:"newPassword" binding:"required"`
  28. }
  29. type UserService interface {
  30. Register(ctx context.Context, req *RegisterRequest) error
  31. Login(ctx context.Context, req *LoginRequest) (string, error)
  32. GetProfile(ctx context.Context, userId string) (*model.User, error)
  33. UpdateProfile(ctx context.Context, userId string, req *UpdateProfileRequest) error
  34. GenerateToken(ctx context.Context, userId string) (string, error)
  35. }
  36. type userService struct {
  37. userRepo repository.UserRepository
  38. *Service
  39. }
  40. func NewUserService(service *Service, userRepo repository.UserRepository) UserService {
  41. return &userService{
  42. userRepo: userRepo,
  43. Service: service,
  44. }
  45. }
  46. func (s *userService) Register(ctx context.Context, req *RegisterRequest) error {
  47. // 检查用户名是否已存在
  48. if user, err := s.userRepo.GetByUsername(ctx, req.Username); err == nil && user != nil {
  49. return errors.New("username already exists")
  50. }
  51. hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
  52. if err != nil {
  53. return errors.Wrap(err, "failed to hash password")
  54. }
  55. // 生成用户ID
  56. userId, err := s.sid.GenString()
  57. if err != nil {
  58. return errors.Wrap(err, "failed to generate user ID")
  59. }
  60. // 创建用户
  61. user := &model.User{
  62. UserId: userId,
  63. Username: req.Username,
  64. Password: string(hashedPassword),
  65. Email: req.Email,
  66. }
  67. if err = s.userRepo.Create(ctx, user); err != nil {
  68. return errors.Wrap(err, "failed to create user")
  69. }
  70. return nil
  71. }
  72. func (s *userService) Login(ctx context.Context, req *LoginRequest) (string, error) {
  73. user, err := s.userRepo.GetByUsername(ctx, req.Username)
  74. if err != nil || user == nil {
  75. return "", errors.Wrap(err, "failed to get user by username")
  76. }
  77. err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
  78. if err != nil {
  79. return "", errors.Wrap(err, "failed to hash password")
  80. }
  81. // 生成JWT token
  82. token, err := s.GenerateToken(ctx, user.UserId)
  83. if err != nil {
  84. return "", errors.Wrap(err, "failed to generate JWT token")
  85. }
  86. return token, nil
  87. }
  88. func (s *userService) GetProfile(ctx context.Context, userId string) (*model.User, error) {
  89. user, err := s.userRepo.GetByID(ctx, userId)
  90. if err != nil {
  91. return nil, errors.Wrap(err, "failed to get user by ID")
  92. }
  93. return user, nil
  94. }
  95. func (s *userService) UpdateProfile(ctx context.Context, userId string, req *UpdateProfileRequest) error {
  96. user, err := s.userRepo.GetByID(ctx, userId)
  97. if err != nil {
  98. return errors.Wrap(err, "failed to get user by ID")
  99. }
  100. user.Email = req.Email
  101. user.Nickname = req.Nickname
  102. if err = s.userRepo.Update(ctx, user); err != nil {
  103. return errors.Wrap(err, "failed to update user")
  104. }
  105. return nil
  106. }
  107. func (s *userService) GenerateToken(ctx context.Context, userId string) (string, error) {
  108. // 生成JWT token
  109. s.jwt.GenToken(userId, time.Now().Add(time.Hour*24*90))
  110. token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
  111. "userId": userId,
  112. "exp": time.Now().Add(time.Hour * 24).Unix(),
  113. }).SignedString([]byte("secret"))
  114. if err != nil {
  115. return "", errors.Wrap(err, "failed to generate JWT token")
  116. }
  117. return token, nil
  118. }