Class: Legate::Auth::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/legate/auth/runner.rb

Overview

Runner provides the execution environment for fiber-based authentication flows. It handles creating and managing authentication coordinators, running tasks within a fiber, and handling authentication requests/responses.

Instance Method Summary collapse

Constructor Details

#initialize(session_service:, token_store: nil, token_manager: nil) ⇒ Runner

Initialize a new authentication runner

Parameters:



21
22
23
24
25
26
# File 'lib/legate/auth/runner.rb', line 21

def initialize(session_service:, token_store: nil, token_manager: nil)
  @session_service = session_service
  @token_store = token_store || TokenStore.new(session_service)
  @token_manager = token_manager || TokenManager.new(@token_store)
  @active_coordinators = {}
end

Instance Method Details

#cancel_auth_flow(request_id, reason = nil) ⇒ Boolean

Cancel an active authentication flow

Parameters:

  • request_id (String)

    The request ID for the authentication flow

  • reason (String, nil) (defaults to: nil)

    Optional reason for cancellation

Returns:

  • (Boolean)

    True if the flow was successfully cancelled



135
136
137
138
139
140
141
142
143
# File 'lib/legate/auth/runner.rb', line 135

def cancel_auth_flow(request_id, reason = nil)
  coordinator = @active_coordinators[request_id]

  return false unless coordinator

  result = coordinator.cancel(reason)
  @active_coordinators.delete(request_id) if result
  result
end

#handle_auth_response(request_id, response) ⇒ Hash

Handle an authentication response from the client

Parameters:

  • request_id (String)

    The request ID for the authentication flow

  • response (Hash)

    The response from the client

Returns:

  • (Hash)

    The result of handling the response



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/legate/auth/runner.rb', line 86

def handle_auth_response(request_id, response)
  coordinator = @active_coordinators[request_id]

  unless coordinator
    return {
      status: :error,
      error: "No active authentication flow found for request ID: #{request_id}"
    }
  end

  begin
    result = coordinator.resume(response)

    if coordinator.complete?
      if coordinator.success?
        # Authentication completed successfully
        @active_coordinators.delete(request_id)
        {
          status: :completed,
          credential: result
        }
      else
        # Authentication failed
        @active_coordinators.delete(request_id)
        {
          status: :failed,
          error: coordinator.error&.message || 'Authentication failed'
        }
      end
    else
      # Authentication is still in progress, return the next request
      {
        status: :pending,
        request: result
      }
    end
  rescue StandardError => e
    @active_coordinators.delete(request_id)
    {
      status: :error,
      error: "Error handling authentication response: #{e.message}"
    }
  end
end

#run(task, context = nil) {|Hash, nil| ... } ⇒ Object

Run a task within a fiber with authentication handling

Parameters:

  • task (Proc)

    The task to run

  • context (Object) (defaults to: nil)

    The context to run the task in (typically ToolContext)

Yields:

  • (Hash, nil)

    Optional block to handle authentication requests

Returns:

  • (Object)

    The result of the task

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/legate/auth/runner.rb', line 34

def run(task, context = nil, &auth_handler)
  raise ArgumentError, 'Task must be a Proc or lambda' unless task.is_a?(Proc)

  # Create a fiber for the task
  task_fiber = Fiber.new do
    # Make the auth_session method available in the context
    if context && !context.respond_to?(:auth_session)
      context.define_singleton_method(:auth_session) do |scheme, credential, **opts|
        Fiber.yield({
                      action: :authenticate,
                      scheme: scheme,
                      credential: credential,
                      options: opts
                    })
      end
    end

    # Run the task
    task.call
  rescue StandardError => e
    { error: e }
  end

  # Start the fiber
  result = nil
  loop do
    # Resume the fiber and get the next result/yield
    result = task_fiber.resume

    # If the fiber has completed (not yielded), return the result
    break unless task_fiber.alive?

    # Handle authentication requests
    if result.is_a?(Hash) && result[:action] == :authenticate
      handle_authentication_request(result, task_fiber, &auth_handler)
    else
      # For other types of yields, just pass them to the handler if provided
      response = auth_handler ? auth_handler.call(result) : nil
      result = task_fiber.resume(response)
    end
  end

  # If the result is an error hash, raise it
  raise result[:error] if result.is_a?(Hash) && result[:error]

  result
end