// service/auth_service.go package service import ( "errors" "fmt" "time" "api_bb/internal/models" "api_bb/internal/repository" "api_bb/pkg/logger" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" ) type AuthService interface { Register(user *models.User) error Login(email, password string) (*models.User, string, error) GetUserProfile(userID uint) (*models.User, error) UpdateProfile(user *models.User) error } type authService struct { userRepo repository.UserRepository jwtService JWTService logger logger.Interface } func NewAuthService(userRepo repository.UserRepository, jwtService JWTService, log logger.Interface) AuthService { // Создаем логгер с контекстом для сервиса serviceLogger := log.With(zap.String("service", "auth")) return &authService{ userRepo: userRepo, jwtService: jwtService, logger: serviceLogger, } } func (s *authService) UpdateProfile(user *models.User) error { s.logger.Info("Updating user profile", zap.Uint("user_id", user.ID), ) existingUser, err := s.userRepo.FindByID(user.ID) if err != nil { s.logger.Warn("User not found for profile update", zap.Uint("user_id", user.ID), zap.Error(err), ) return fmt.Errorf("user not found") } updateData := &models.User{ ID: existingUser.ID, FirstName: user.FirstName, LastName: user.LastName, Phone: user.Phone, Experience: user.Experience, Goals: user.Goals, Newsletter: user.Newsletter, UpdatedAt: time.Now(), } s.logger.Debug("Profile update data prepared", zap.Uint("user_id", user.ID), zap.String("first_name", updateData.FirstName), zap.String("last_name", updateData.LastName), ) if err := s.userRepo.Update(updateData); err != nil { s.logger.Error("Failed to update user profile", zap.Uint("user_id", user.ID), zap.Error(err), ) return err } user.Email = existingUser.Email user.Password = existingUser.Password user.Role = existingUser.Role user.CreatedAt = existingUser.CreatedAt user.UpdatedAt = updateData.UpdatedAt s.logger.Info("User profile updated successfully", zap.Uint("user_id", user.ID), ) return nil } func (s *authService) Register(user *models.User) error { s.logger.Info("Registering new user", zap.String("email", user.Email), ) existingUser, err := s.userRepo.FindByEmail(user.Email) if err == nil && existingUser != nil { s.logger.Warn("Registration failed - email already exists", zap.String("email", user.Email), ) return errors.New("user with this email already exists") } err = s.userRepo.Create(user) if err != nil { s.logger.Error("Failed to create user in database", zap.String("email", user.Email), zap.Error(err), ) return err } s.logger.Info("User registered successfully", zap.Uint("user_id", user.ID), zap.String("email", user.Email), ) return nil } func (s *authService) Login(email, password string) (*models.User, string, error) { s.logger.Info("Login attempt", zap.String("email", email), zap.Int("password_length", len(password)), ) user, err := s.userRepo.FindByEmail(email) if err != nil { s.logger.Warn("Login failed - user not found", zap.String("email", email), zap.Error(err), ) return nil, "", errors.New("invalid email") } s.logger.Debug("User found for login", zap.Uint("user_id", user.ID), zap.String("stored_hash_prefix", user.Password[:min(10, len(user.Password))]), ) // Проверяем пароль err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) if err != nil { s.logger.Warn("Login failed - invalid password", zap.Uint("user_id", user.ID), zap.String("email", email), zap.Error(err), ) return nil, "", errors.New("invalid password") } s.logger.Info("Login successful", zap.Uint("user_id", user.ID), zap.String("email", email), ) token, err := s.jwtService.GenerateToken(user.ID, user.Email) if err != nil { s.logger.Error("Failed to generate JWT token", zap.Uint("user_id", user.ID), zap.Error(err), ) return nil, "", err } return user, token, nil } func min(a, b int) int { if a < b { return a } return b } func (s *authService) GetUserProfile(userID uint) (*models.User, error) { s.logger.Debug("Getting user profile", zap.Uint("user_id", userID), ) user, err := s.userRepo.FindByID(userID) if err != nil { s.logger.Warn("Failed to get user profile", zap.Uint("user_id", userID), zap.Error(err), ) return nil, err } return user, nil }