package grpc import ( "context" "fmt" "rag/file-system/api/proto" "rag/file-system/internal/common" "time" "github.com/patrickmn/go-cache" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) type TokenInfo struct { Valid bool UserId string Username string Email string Roles []string Permissions []string ExpiresAt int64 } type AuthClient struct { conn *grpc.ClientConn client proto.AuthServiceClient cache *cache.Cache } func NewAuthClient(addr string) (*AuthClient, error) { conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { return nil, fmt.Errorf("gRPC connect failed: %w", err) } common.Logger.Info("gRPC auth client connected", "addr", addr) return &AuthClient{ conn: conn, client: proto.NewAuthServiceClient(conn), cache: cache.New(2*time.Minute, 5*time.Minute), }, nil } func (a *AuthClient) ValidateToken(ctx context.Context, token string) (*TokenInfo, error) { if cached, ok := a.cache.Get(token); ok { return cached.(*TokenInfo), nil } resp, err := a.client.ValidateToken(ctx, &proto.ValidateTokenRequest{Token: token}) if err != nil { return nil, fmt.Errorf("gRPC ValidateToken failed: %w", err) } info := &TokenInfo{ Valid: resp.Valid, UserId: resp.UserId, Username: resp.Username, Email: resp.Email, Roles: resp.Roles, Permissions: resp.Permissions, ExpiresAt: resp.ExpiresAt, } if info.Valid { ttl := a.cacheTTL(resp.ExpiresAt) a.cache.Set(token, info, ttl) } return info, nil } func (a *AuthClient) HasPermission(token, permission string) (bool, error) { resp, err := a.client.CheckPermission(context.Background(), &proto.CheckPermissionRequest{ Token: token, Permission: permission, }) if err != nil { return false, fmt.Errorf("gRPC CheckPermission failed: %w", err) } return resp.Allowed, nil } func (a *AuthClient) Close() error { return a.conn.Close() } func (a *AuthClient) cacheTTL(expiresAt int64) time.Duration { expires := time.Unix(expiresAt, 0) ttl := time.Until(expires) - 30*time.Second if ttl < time.Minute { ttl = time.Minute } if ttl > 2*time.Minute { ttl = 2 * time.Minute } return ttl }