Files
Mini-ERP-app/core-service/internal/service/auth_service.go
Andrey Epifantsev ae84ce74a7 feat: завершён этап 2 - Аутентификация Core Service
- Реализована JWT аутентификация с organization-scope
- Добавлено хеширование паролей через bcrypt
- Созданы репозитории для организаций и пользователей
- Реализован AuthService с бизнес-логикой
- Добавлен AuthMiddleware для проверки токенов
- Созданы handlers для регистрации и входа
- Обновлён API сервер для использования аутентификации

Готово для этапа 3 - API структура
2025-08-27 14:56:33 +04:00

119 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"time"
"erp-mvp/core-service/internal/auth"
"erp-mvp/core-service/internal/models"
"erp-mvp/core-service/internal/repository"
"github.com/google/uuid"
)
type AuthService interface {
Register(ctx context.Context, req *models.RegisterRequest) (*models.LoginResponse, error)
Login(ctx context.Context, req *models.LoginRequest) (*models.LoginResponse, error)
}
type authService struct {
orgRepo repository.OrganizationRepository
userRepo repository.UserRepository
jwtService *auth.JWTService
}
func NewAuthService(orgRepo repository.OrganizationRepository, userRepo repository.UserRepository, jwtService *auth.JWTService) AuthService {
return &authService{
orgRepo: orgRepo,
userRepo: userRepo,
jwtService: jwtService,
}
}
func (s *authService) Register(ctx context.Context, req *models.RegisterRequest) (*models.LoginResponse, error) {
// Проверяем, что пользователь с таким email не существует
existingUser, err := s.userRepo.GetByEmail(ctx, req.UserEmail)
if err == nil && existingUser != nil {
return nil, &ValidationError{Message: "User with this email already exists"}
}
// Создаём организацию
orgID := uuid.New()
org := &models.Organization{
ID: orgID,
Name: req.OrganizationName,
Type: req.OrganizationType,
Settings: models.JSON{},
CreatedAt: time.Now(),
}
if err := s.orgRepo.Create(ctx, org); err != nil {
return nil, err
}
// Хешируем пароль
passwordHash, err := auth.HashPassword(req.UserPassword)
if err != nil {
return nil, err
}
// Создаём пользователя
userID := uuid.New()
user := &models.User{
ID: userID,
OrganizationID: orgID,
Email: req.UserEmail,
Role: "admin", // Первый пользователь становится админом
CreatedAt: time.Now(),
}
if err := s.userRepo.Create(ctx, user, passwordHash); err != nil {
return nil, err
}
// Генерируем JWT токен
token, err := s.jwtService.GenerateToken(user.ID, org.ID, user.Email, user.Role)
if err != nil {
return nil, err
}
return &models.LoginResponse{
Token: token,
User: *user,
ExpiresAt: time.Now().Add(24 * time.Hour), // TTL из конфигурации
}, nil
}
func (s *authService) Login(ctx context.Context, req *models.LoginRequest) (*models.LoginResponse, error) {
// Получаем пользователя по email
user, err := s.userRepo.GetByEmail(ctx, req.Email)
if err != nil {
return nil, &ValidationError{Message: "Invalid email or password"}
}
// Проверяем пароль
if !auth.CheckPassword(req.Password, user.PasswordHash) {
return nil, &ValidationError{Message: "Invalid email or password"}
}
// Генерируем JWT токен
token, err := s.jwtService.GenerateToken(user.ID, user.OrganizationID, user.Email, user.Role)
if err != nil {
return nil, err
}
return &models.LoginResponse{
Token: token,
User: *user,
ExpiresAt: time.Now().Add(24 * time.Hour), // TTL из конфигурации
}, nil
}
// ValidationError ошибка валидации
type ValidationError struct {
Message string
}
func (e *ValidationError) Error() string {
return e.Message
}