package service import ( "context" "errors" "bugulma/backend/internal/domain" "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" ) type AuthService struct { userRepo domain.UserRepository jwtService *JWTService } func NewAuthService(userRepo domain.UserRepository, jwtSecret string) *AuthService { return &AuthService{ userRepo: userRepo, jwtService: NewJWTService(jwtSecret), } } type Claims struct { UserID string `json:"user_id"` Email string `json:"email"` Name string `json:"name"` Role string `json:"role"` jwt.RegisteredClaims } func (s *AuthService) Login(ctx context.Context, email, password string) (string, *domain.User, error) { user, err := s.userRepo.GetByEmail(ctx, email) if err != nil { return "", nil, errors.New("invalid credentials") } // Verify password if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { return "", nil, errors.New("invalid credentials") } // For now, use empty orgID - this would be determined by user's primary organization // In a real implementation, this might involve checking user's organization memberships token, err := s.jwtService.GenerateToken(user, "") if err != nil { return "", nil, err } return token, user, nil } func (s *AuthService) ValidateToken(ctx context.Context, tokenString string) (*domain.User, error) { claims, err := s.jwtService.ValidateToken(tokenString) if err != nil { return nil, err } user, err := s.userRepo.GetByID(ctx, claims.UserID) if err != nil { return nil, err } return user, nil } // ValidateTokenWithClaims validates token and returns both user and claims func (s *AuthService) ValidateTokenWithClaims(ctx context.Context, tokenString string) (*domain.User, *JWTClaims, error) { claims, err := s.jwtService.ValidateToken(tokenString) if err != nil { return nil, nil, err } user, err := s.userRepo.GetByID(ctx, claims.UserID) if err != nil { return nil, nil, err } return user, claims, nil }