veza/veza-backend-api/internal/services/chat_service.go
2025-12-03 20:29:37 +01:00

63 lines
1.3 KiB
Go

package services
import (
"errors"
"fmt"
"github.com/google/uuid"
"time"
"github.com/golang-jwt/jwt/v5"
"go.uber.org/zap"
)
type ChatService struct {
jwtSecret string
logger *zap.Logger
}
func NewChatService(jwtSecret string, logger *zap.Logger) *ChatService {
if logger == nil {
logger = zap.NewNop()
}
return &ChatService{
jwtSecret: jwtSecret,
logger: logger,
}
}
type ChatTokenResponse struct {
Token string `json:"token"`
ExpiresIn int64 `json:"expires_in"`
WSUrl string `json:"ws_url"`
}
func (s *ChatService) GenerateToken(userID uuid.UUID, username string) (*ChatTokenResponse, error) {
if s.jwtSecret == "" {
return nil, errors.New("JWT secret is not configured")
}
now := time.Now()
expiration := 15 * time.Minute
exp := now.Add(expiration)
claims := jwt.MapClaims{
"sub": fmt.Sprintf("%d", userID),
"name": username,
"aud": "veza-chat",
"iss": "veza-backend",
"iat": now.Unix(),
"exp": exp.Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(s.jwtSecret))
if err != nil {
return nil, fmt.Errorf("failed to sign token: %w", err)
}
return &ChatTokenResponse{
Token: tokenString,
ExpiresIn: int64(expiration.Seconds()),
WSUrl: "/ws", // Relative path, frontend appends base URL
}, nil
}