package service import ( "context" "errors" "api_es/internal/dto" "api_es/internal/models" "api_es/internal/repository" "api_es/internal/utils" "golang.org/x/crypto/bcrypt" ) var ( ErrUserNotFound = errors.New("user not found") ErrInvalidCredentials = errors.New("invalid credentials") ErrUserAlreadyExists = errors.New("user already exists") ErrInvalidPassword = errors.New("invalid password") ) type UserService interface { Register(ctx context.Context, req dto.RegisterRequest) (*dto.AuthResponse, error) Login(ctx context.Context, req dto.LoginRequest) (*dto.AuthResponse, error) GetUser(ctx context.Context, id uint) (*dto.UserResponse, error) UpdateUser(ctx context.Context, id uint, req dto.UpdateUserRequest) (*dto.UserResponse, error) DeleteUser(ctx context.Context, id uint) error ListUsers(ctx context.Context, limit, offset int) ([]*dto.UserResponse, error) GetUserProfile(ctx context.Context, id uint) (*dto.UserResponse, error) } type userService struct { userRepo repository.UserRepository jwtUtil *utils.JWTUtil } func NewUserService(userRepo repository.UserRepository, jwtUtil *utils.JWTUtil) UserService { return &userService{ userRepo: userRepo, jwtUtil: jwtUtil, } } func (s *userService) Register(ctx context.Context, req dto.RegisterRequest) (*dto.AuthResponse, error) { // Проверяем существование пользователя existingUser, _ := s.userRepo.GetByEmail(ctx, req.Email) if existingUser != nil { return nil, ErrUserAlreadyExists } // Хешируем пароль hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { return nil, err } // Создаем пользователя user := &models.User{ Email: req.Email, PasswordHash: string(hashedPassword), FullName: req.FullName, FirstName: req.FirstName, LastName: req.LastName, Phone: req.Phone, City: req.City, IsActive: true, IsVerified: false, Role: "user", } if err := s.userRepo.Create(ctx, user); err != nil { return nil, err } // Генерируем токен token, err := s.jwtUtil.GenerateToken(user.ID, user.Email, user.Role) if err != nil { return nil, err } userResponse := dto.ToUserResponse(user) return &dto.AuthResponse{ Token: token, User: userResponse, }, nil } func (s *userService) Login(ctx context.Context, req dto.LoginRequest) (*dto.AuthResponse, error) { // Находим пользователя по email user, err := s.userRepo.GetByEmail(ctx, req.Email) if err != nil { return nil, ErrInvalidCredentials } // Проверяем пароль if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil { return nil, ErrInvalidCredentials } // Проверяем активность пользователя if !user.IsActive { return nil, errors.New("account is deactivated") } // Генерируем токен token, err := s.jwtUtil.GenerateToken(user.ID, user.Email, user.Role) if err != nil { return nil, err } userResponse := dto.ToUserResponse(user) return &dto.AuthResponse{ Token: token, User: userResponse, }, nil } func (s *userService) GetUser(ctx context.Context, id uint) (*dto.UserResponse, error) { user, err := s.userRepo.GetByID(ctx, id) if err != nil { return nil, ErrUserNotFound } response := dto.ToUserResponse(user) return &response, nil } func (s *userService) UpdateUser(ctx context.Context, id uint, req dto.UpdateUserRequest) (*dto.UserResponse, error) { user, err := s.userRepo.GetByID(ctx, id) if err != nil { return nil, ErrUserNotFound } // Обновляем поля if req.FullName != "" { user.FullName = req.FullName } if req.FirstName != "" { user.FirstName = req.FirstName } if req.LastName != "" { user.LastName = req.LastName } if req.Phone != "" { user.Phone = req.Phone } if req.City != "" { user.City = req.City } if req.OrganizationForm != "" { user.OrganizationForm = req.OrganizationForm } if req.OrganizationName != "" { user.OrganizationName = req.OrganizationName } if req.OrganizationShort != "" { user.OrganizationShort = req.OrganizationShort } if req.INN != "" { user.INN = req.INN } if req.PersonalINN != "" { user.PersonalINN = req.PersonalINN } if err := s.userRepo.Update(ctx, user); err != nil { return nil, err } response := dto.ToUserResponse(user) return &response, nil } func (s *userService) DeleteUser(ctx context.Context, id uint) error { return s.userRepo.Delete(ctx, id) } func (s *userService) ListUsers(ctx context.Context, limit, offset int) ([]*dto.UserResponse, error) { users, err := s.userRepo.List(ctx, limit, offset) if err != nil { return nil, err } responses := make([]*dto.UserResponse, len(users)) for i, user := range users { response := dto.ToUserResponse(user) responses[i] = &response } return responses, nil } func (s *userService) GetUserProfile(ctx context.Context, id uint) (*dto.UserResponse, error) { return s.GetUser(ctx, id) }