Class: Foobara::CommandConnector::Request

Inherits:
Object
  • Object
show all
Includes:
NestedTransactionable, TruncatedInspect
Defined in:
foobara-0.6.1/projects/command_connectors/src/command_connector/request.rb

Constant Summary

Constants included from TruncatedInspect

TruncatedInspect::MAX_LENGTH

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from NestedTransactionable

#auto_detect_current_transactions, #commit_transaction, #commit_transaction_if_open, #open_transaction, #opened_transactions, relevant_entity_classes_for_type, #relevant_entity_classes_for_type, #rollback_transaction, #transactions, #use_transaction, with_needed_transactions_for_type

Methods included from TruncatedInspect

#inspect, truncating

Constructor Details

#initialize(**opts) ⇒ Request

Returns a new instance of Request.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'projects/command_connectors/src/command_connector/request.rb', line 23

def initialize(**opts)
  valid_keys = [:inputs, :full_command_name, :action, :serializers, :authenticator, :auth_mappers]

  invalid_keys = opts.keys - valid_keys

  unless invalid_keys.empty?
    # simplecov:disable
    raise ArgumentError, "invalid keys: #{invalid_keys} expected only #{valid_keys}"
    # simplecov:enable
  end

  self.inputs = opts[:inputs] if opts.key?(:inputs)
  self.action = opts[:action] if opts.key?(:action)
  self.auth_mappers = opts[:auth_mappers] if opts.key?(:auth_mappers)
  self.authenticator = opts[:authenticator] if opts.key?(:authenticator)
  self.full_command_name = opts[:full_command_name] if opts.key?(:full_command_name)
  self.serializers = Util.array(opts[:serializers]) if opts.key?(:serializers)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'projects/command_connectors/src/command_connector/request.rb', line 102

def method_missing(method_name, ...)
  if auth_mapped_method?(method_name)
    auth_mapped_value_for(method_name)
  else
    # simplecov:disable
    super
    # simplecov:enable
  end
end

Instance Attribute Details

#actionObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def action
  @action
end

#auth_mappersObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def auth_mappers
  @auth_mappers
end

#authenticated_credentialObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def authenticated_credential
  @authenticated_credential
end

#authenticated_userObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def authenticated_user
  @authenticated_user
end

#authenticatorObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def authenticator
  @authenticator
end

#commandObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def command
  @command
end

#command_classObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def command_class
  @command_class
end

#command_connectorObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def command_connector
  @command_connector
end

#errorObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def error
  @error
end

#full_command_nameObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def full_command_name
  @full_command_name
end

#inputsObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def inputs
  @inputs
end

#responseObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def response
  @response
end

#serializersObject

TODO: this feels like a smell of some sort...



8
9
10
# File 'projects/command_connectors/src/command_connector/request.rb', line 8

def serializers
  @serializers
end

Instance Method Details

#auth_mapped_method?(method_name) ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
# File 'projects/command_connectors/src/command_connector/request.rb', line 82

def auth_mapped_method?(method_name)
  auth_mappers&.key?(method_name)
end

#auth_mapped_value_for(name) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
# File 'projects/command_connectors/src/command_connector/request.rb', line 90

def auth_mapped_value_for(name)
  return unless authenticated_user

  @auth_mapper_cache ||= {}

  if @auth_mapper_cache.key?(name)
    @auth_mapper_cache[name]
  else
    @auth_mapper_cache[name] = auth_mapper_for(name)&.process_value!(authenticated_user)
  end
end

#auth_mapper_for(name) ⇒ Object



86
87
88
# File 'projects/command_connectors/src/command_connector/request.rb', line 86

def auth_mapper_for(name)
  auth_mappers&.[](name.to_sym)
end

#authenticateObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'projects/command_connectors/src/command_connector/request.rb', line 51

def authenticate
  return if error
  return unless requires_authentication? || authentication_optional?

  unless authenticator
    raise CommandConnector::NoAuthenticatorGivenError,
          "Running a #{command_class.full_command_name} via #{command_connector} " \
          "requires an authenticator but this connector does not have one"
  end

  authenticated_user, authenticated_credential = authenticator.authenticate(self)

  # TODO: why are these on the command instead of the request??
  self.authenticated_user = authenticated_user
  self.authenticated_credential = authenticated_credential

  return unless requires_authentication?

  unless authenticated_user
    self.error = CommandConnector::UnauthenticatedError.new
  end
end

#authentication_optional?Boolean

Returns:

  • (Boolean)


74
75
76
# File 'projects/command_connectors/src/command_connector/request.rb', line 74

def authentication_optional?
  command_class.respond_to?(:authentication_optional) && command_class.authentication_optional
end

#error_collectionObject



162
163
164
# File 'projects/command_connectors/src/command_connector/request.rb', line 162

def error_collection
  outcome.error_collection
end

#mutate_requestObject



42
43
44
45
46
47
48
49
# File 'projects/command_connectors/src/command_connector/request.rb', line 42

def mutate_request
  return if error

  # TODO: we really need to revisit these interfaces. Something is wrong.
  if command_class.respond_to?(:mutate_request)
    command_class.mutate_request(self)
  end
end

#outcomeObject



150
151
152
153
154
155
156
# File 'projects/command_connectors/src/command_connector/request.rb', line 150

def outcome
  if error
    Outcome.error(error)
  else
    command&.outcome
  end
end

#relevant_entity_classesObject

TODO: move this to entity_plumbing



167
168
169
170
171
172
173
174
175
176
# File 'projects/command_connectors/src/command_connector/request.rb', line 167

def relevant_entity_classes
  if command_class.is_a?(::Class) && command_class < TransformedCommand
    if authenticator.respond_to?(:relevant_entity_classes)
      entity_classes = authenticator.relevant_entity_classes(self)
      [*entity_classes, *relevant_entity_classes_from_inputs_transformer]
    else
      relevant_entity_classes_from_inputs_transformer
    end
  end || EMPTY_ARRAY
end

#requires_authentication?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'projects/command_connectors/src/command_connector/request.rb', line 78

def requires_authentication?
  command_class.respond_to?(:requires_authentication) && command_class.requires_authentication
end

#respond_to_missing?(method_name, private = false) ⇒ Boolean

Returns:

  • (Boolean)


112
113
114
# File 'projects/command_connectors/src/command_connector/request.rb', line 112

def respond_to_missing?(method_name, private = false)
  auth_mapped_method?(method_name) || super
end

#response_bodyObject



133
134
135
136
137
138
139
140
141
142
143
144
# File 'projects/command_connectors/src/command_connector/request.rb', line 133

def response_body
  @response_body ||= begin
    # TODO: should we have separate ways to register success and failure serializers?
    body = success? ? result : error_collection

    if serializer
      serializer.process_value!(body)
    else
      body
    end
  end
end

#resultObject



158
159
160
# File 'projects/command_connectors/src/command_connector/request.rb', line 158

def result
  outcome.result
end

#serializerObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'projects/command_connectors/src/command_connector/request.rb', line 116

def serializer
  return @serializer if defined?(@serializer)

  if serializers.nil? || serializers.empty?
    @serializer = nil
    return
  end

  actual_serializers = objects_to_serializers(serializers)

  @serializer = if actual_serializers.size == 1
                  actual_serializers[0]
                else
                  Value::Processor::Pipeline.new(processors: actual_serializers)
                end
end

#success?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'projects/command_connectors/src/command_connector/request.rb', line 146

def success?
  outcome.success?
end