hoodoo 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/bin/hoodoo +5 -0
  3. data/lib/hoodoo.rb +27 -0
  4. data/lib/hoodoo/active.rb +32 -0
  5. data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
  6. data/lib/hoodoo/active/active_record/base.rb +81 -0
  7. data/lib/hoodoo/active/active_record/creator.rb +134 -0
  8. data/lib/hoodoo/active/active_record/dated.rb +343 -0
  9. data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
  10. data/lib/hoodoo/active/active_record/finder.rb +606 -0
  11. data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
  12. data/lib/hoodoo/active/active_record/secure.rb +431 -0
  13. data/lib/hoodoo/active/active_record/support.rb +106 -0
  14. data/lib/hoodoo/active/active_record/translated.rb +87 -0
  15. data/lib/hoodoo/active/active_record/uuid.rb +80 -0
  16. data/lib/hoodoo/active/active_record/writer.rb +321 -0
  17. data/lib/hoodoo/client.rb +23 -0
  18. data/lib/hoodoo/client/augmented_array.rb +29 -0
  19. data/lib/hoodoo/client/augmented_base.rb +168 -0
  20. data/lib/hoodoo/client/augmented_hash.rb +23 -0
  21. data/lib/hoodoo/client/client.rb +354 -0
  22. data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
  23. data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
  24. data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
  25. data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
  26. data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
  27. data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
  28. data/lib/hoodoo/client/headers.rb +269 -0
  29. data/lib/hoodoo/communicators.rb +23 -0
  30. data/lib/hoodoo/communicators/fast.rb +44 -0
  31. data/lib/hoodoo/communicators/pool.rb +601 -0
  32. data/lib/hoodoo/communicators/slow.rb +84 -0
  33. data/lib/hoodoo/data.rb +51 -0
  34. data/lib/hoodoo/data/resources/caller.rb +39 -0
  35. data/lib/hoodoo/data/resources/errors.rb +28 -0
  36. data/lib/hoodoo/data/resources/log.rb +31 -0
  37. data/lib/hoodoo/data/resources/session.rb +26 -0
  38. data/lib/hoodoo/data/types/error_primitive.rb +27 -0
  39. data/lib/hoodoo/data/types/permissions.rb +40 -0
  40. data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
  41. data/lib/hoodoo/data/types/permissions_full.rb +28 -0
  42. data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
  43. data/lib/hoodoo/discovery.rb +20 -0
  44. data/lib/hoodoo/errors.rb +19 -0
  45. data/lib/hoodoo/errors/error_descriptions.rb +229 -0
  46. data/lib/hoodoo/errors/errors.rb +322 -0
  47. data/lib/hoodoo/generator.rb +139 -0
  48. data/lib/hoodoo/logger.rb +23 -0
  49. data/lib/hoodoo/logger/fast_writer.rb +27 -0
  50. data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
  51. data/lib/hoodoo/logger/logger.rb +387 -0
  52. data/lib/hoodoo/logger/slow_writer.rb +49 -0
  53. data/lib/hoodoo/logger/writer_mixin.rb +52 -0
  54. data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
  55. data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
  56. data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
  57. data/lib/hoodoo/middleware.rb +33 -0
  58. data/lib/hoodoo/presenters.rb +45 -0
  59. data/lib/hoodoo/presenters/base.rb +281 -0
  60. data/lib/hoodoo/presenters/base_dsl.rb +519 -0
  61. data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
  62. data/lib/hoodoo/presenters/embedding.rb +232 -0
  63. data/lib/hoodoo/presenters/types/array.rb +118 -0
  64. data/lib/hoodoo/presenters/types/boolean.rb +26 -0
  65. data/lib/hoodoo/presenters/types/date.rb +26 -0
  66. data/lib/hoodoo/presenters/types/date_time.rb +26 -0
  67. data/lib/hoodoo/presenters/types/decimal.rb +47 -0
  68. data/lib/hoodoo/presenters/types/enum.rb +55 -0
  69. data/lib/hoodoo/presenters/types/field.rb +158 -0
  70. data/lib/hoodoo/presenters/types/float.rb +26 -0
  71. data/lib/hoodoo/presenters/types/hash.rb +361 -0
  72. data/lib/hoodoo/presenters/types/integer.rb +26 -0
  73. data/lib/hoodoo/presenters/types/object.rb +117 -0
  74. data/lib/hoodoo/presenters/types/string.rb +53 -0
  75. data/lib/hoodoo/presenters/types/tags.rb +24 -0
  76. data/lib/hoodoo/presenters/types/text.rb +26 -0
  77. data/lib/hoodoo/presenters/types/uuid.rb +54 -0
  78. data/lib/hoodoo/services.rb +34 -0
  79. data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
  80. data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
  81. data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
  82. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
  83. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
  84. data/lib/hoodoo/services/discovery/discovery.rb +186 -0
  85. data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
  86. data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
  87. data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
  88. data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
  89. data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
  90. data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
  91. data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
  92. data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
  93. data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
  94. data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
  95. data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
  96. data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
  97. data/lib/hoodoo/services/middleware/interaction.rb +127 -0
  98. data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
  99. data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
  100. data/lib/hoodoo/services/services/context.rb +153 -0
  101. data/lib/hoodoo/services/services/implementation.rb +132 -0
  102. data/lib/hoodoo/services/services/interface.rb +934 -0
  103. data/lib/hoodoo/services/services/permissions.rb +250 -0
  104. data/lib/hoodoo/services/services/request.rb +189 -0
  105. data/lib/hoodoo/services/services/response.rb +316 -0
  106. data/lib/hoodoo/services/services/service.rb +141 -0
  107. data/lib/hoodoo/services/services/session.rb +729 -0
  108. data/lib/hoodoo/utilities.rb +12 -0
  109. data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
  110. data/lib/hoodoo/utilities/utilities.rb +380 -0
  111. data/lib/hoodoo/utilities/uuid.rb +44 -0
  112. data/lib/hoodoo/version.rb +17 -0
  113. data/spec/active/active_record/base_spec.rb +57 -0
  114. data/spec/active/active_record/creator_spec.rb +88 -0
  115. data/spec/active/active_record/dated_spec.rb +248 -0
  116. data/spec/active/active_record/error_mapping_spec.rb +360 -0
  117. data/spec/active/active_record/finder_spec.rb +744 -0
  118. data/spec/active/active_record/search_helper_spec.rb +384 -0
  119. data/spec/active/active_record/secure_spec.rb +435 -0
  120. data/spec/active/active_record/support_spec.rb +225 -0
  121. data/spec/active/active_record/translated_spec.rb +19 -0
  122. data/spec/active/active_record/uuid_spec.rb +72 -0
  123. data/spec/active/active_record/writer_spec.rb +272 -0
  124. data/spec/alchemy/alchemy-amq.rb +33 -0
  125. data/spec/client/augmented_array_spec.rb +15 -0
  126. data/spec/client/augmented_base_spec.rb +50 -0
  127. data/spec/client/augmented_hash_spec.rb +15 -0
  128. data/spec/client/client_spec.rb +955 -0
  129. data/spec/client/endpoint/endpoint_spec.rb +70 -0
  130. data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
  131. data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
  132. data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
  133. data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
  134. data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
  135. data/spec/client/headers_spec.rb +172 -0
  136. data/spec/communicators/fast_spec.rb +9 -0
  137. data/spec/communicators/pool_spec.rb +339 -0
  138. data/spec/communicators/slow_spec.rb +15 -0
  139. data/spec/data/resources/caller_spec.rb +156 -0
  140. data/spec/data/resources/errors_spec.rb +22 -0
  141. data/spec/data/resources/log_spec.rb +20 -0
  142. data/spec/data/resources/session_spec.rb +15 -0
  143. data/spec/data/types/error_primitive_spec.rb +15 -0
  144. data/spec/data/types/permissions_defaults_spec.rb +25 -0
  145. data/spec/data/types/permissions_full_spec.rb +44 -0
  146. data/spec/data/types/permissions_resources_spec.rb +34 -0
  147. data/spec/data/types/permissions_spec.rb +37 -0
  148. data/spec/errors/error_descriptions_spec.rb +98 -0
  149. data/spec/errors/errors_spec.rb +346 -0
  150. data/spec/integration/service_actions_spec.rb +112 -0
  151. data/spec/logger/fast_writer_spec.rb +18 -0
  152. data/spec/logger/logger_spec.rb +259 -0
  153. data/spec/logger/slow_writer_spec.rb +144 -0
  154. data/spec/logger/writers/file_writer_spec.rb +37 -0
  155. data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
  156. data/spec/logger/writers/stream_writer_spec.rb +38 -0
  157. data/spec/presenters/base_dsl_spec.rb +111 -0
  158. data/spec/presenters/base_spec.rb +871 -0
  159. data/spec/presenters/common_resource_fields_spec.rb +30 -0
  160. data/spec/presenters/embedding_spec.rb +87 -0
  161. data/spec/presenters/types/array_spec.rb +249 -0
  162. data/spec/presenters/types/boolean_spec.rb +51 -0
  163. data/spec/presenters/types/date_spec.rb +57 -0
  164. data/spec/presenters/types/date_time_spec.rb +59 -0
  165. data/spec/presenters/types/decimal_spec.rb +58 -0
  166. data/spec/presenters/types/enum_spec.rb +71 -0
  167. data/spec/presenters/types/field_spec.rb +77 -0
  168. data/spec/presenters/types/float_spec.rb +50 -0
  169. data/spec/presenters/types/hash_spec.rb +1069 -0
  170. data/spec/presenters/types/integer_spec.rb +50 -0
  171. data/spec/presenters/types/object_spec.rb +177 -0
  172. data/spec/presenters/types/string_spec.rb +65 -0
  173. data/spec/presenters/types/tags_spec.rb +56 -0
  174. data/spec/presenters/types/text_spec.rb +50 -0
  175. data/spec/presenters/types/uuid_spec.rb +46 -0
  176. data/spec/presenters/walk_spec.rb +198 -0
  177. data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
  178. data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
  179. data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
  180. data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
  181. data/spec/services/discovery/discovery_spec.rb +73 -0
  182. data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
  183. data/spec/services/discovery/results/for_http_spec.rb +37 -0
  184. data/spec/services/discovery/results/for_local_spec.rb +21 -0
  185. data/spec/services/discovery/results/for_remote_spec.rb +15 -0
  186. data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
  187. data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
  188. data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
  189. data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
  190. data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
  191. data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
  192. data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
  193. data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
  194. data/spec/services/middleware/middleware_cors_spec.rb +93 -0
  195. data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
  196. data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
  197. data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
  198. data/spec/services/middleware/middleware_logging_spec.rb +356 -0
  199. data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
  200. data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
  201. data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
  202. data/spec/services/middleware/middleware_public_spec.rb +238 -0
  203. data/spec/services/middleware/middleware_spec.rb +1569 -0
  204. data/spec/services/middleware/string_inquirer_spec.rb +30 -0
  205. data/spec/services/services/application_spec.rb +74 -0
  206. data/spec/services/services/context_spec.rb +48 -0
  207. data/spec/services/services/implementation_spec.rb +45 -0
  208. data/spec/services/services/interface_spec.rb +262 -0
  209. data/spec/services/services/permissions_spec.rb +249 -0
  210. data/spec/services/services/request_spec.rb +95 -0
  211. data/spec/services/services/response_spec.rb +250 -0
  212. data/spec/services/services/session_spec.rb +432 -0
  213. data/spec/spec_helper.rb +298 -0
  214. data/spec/utilities/utilities_spec.rb +537 -0
  215. data/spec/utilities/uuid_spec.rb +20 -0
  216. metadata +615 -0
@@ -0,0 +1,119 @@
1
+ ########################################################################
2
+ # File:: amqp_log_writer.rb
3
+ # (C):: Loyalty New Zealand 2014
4
+ #
5
+ # Purpose:: Structured logging support for the middleware.
6
+ # ----------------------------------------------------------------------
7
+ # 20-Nov-2014 (ADH): Created.
8
+ # 16-Dec-2014 (ADH): Changed into a new Hoodoo::Logger style
9
+ # instantiable log writer.
10
+ ########################################################################
11
+
12
+ module Hoodoo; module Services
13
+ class Middleware
14
+
15
+ # Log writer which sends structured messages to an AMQP-based queue via
16
+ # the AlchemyAMQ gems. A Hoodoo::Logger::FastWriter subclass, since though
17
+ # talking to the queue might be comparatively slow, Alchemy itself uses an
18
+ # asynchronous Thread for this so there's no need to add another one for
19
+ # this logger.
20
+ #
21
+ # See also Hoodoo::Logger and Hoodoo::Services::Middleware::AMQPLogMessage.
22
+ #
23
+ class AMQPLogWriter < Hoodoo::Logger::FastWriter
24
+
25
+ # Create an AMQP logger instance.
26
+ #
27
+ # +alchemy+:: The Alchemy endpoint to use for sending messages to the
28
+ # AMQP-based queue.
29
+ #
30
+ # +queue_name+:: The queue name (as a String) to use. Optional. If
31
+ # omitted, reads +ENV[ 'AMQ_LOGGING_ENDPOINT' ]+ or if
32
+ # that is unset, defaults to +platform.logging+.
33
+ #
34
+ # If you're running with Rack on top of Alchemy, then the +call+ method's
35
+ # +env+ parameter containing the Rack environment should have a key of
36
+ # +rack.alchemy+ or +alchemy+ with a value that can be assigned to the
37
+ # +alchemy+ parameter. The logger will then use the active Alchemy
38
+ # service to send messages to its configured named queue.
39
+ #
40
+ def initialize( alchemy, queue_name = nil )
41
+ @alchemy = alchemy
42
+ @queue_name = queue_name || ENV[ 'AMQ_LOGGING_ENDPOINT' ] || 'platform.logging'
43
+ end
44
+
45
+ # Custom implementation of the Hoodoo::Logger::WriterMixin#report
46
+ # interface. See that method for parameter details.
47
+ #
48
+ # The middleware custom logger has expectations about the data payload.
49
+ # It expects these optional but recommended (where the information is
50
+ # available / has been generated) keys/values:
51
+ #
52
+ # +:id+:: A UUID (via Hoodoo::UUID::generate) to use for this log
53
+ # message - if absent, one is generated automatically.
54
+ #
55
+ # +:session+:: Description of the current request session when available;
56
+ # a Hoodoo::Services::Session as a Hash (via #to_h; keys as
57
+ # Strings). The Caller UUID, identity Participant UUID and
58
+ # identity Outlet UUID are sent as independent, searchable
59
+ # fields in the log payload.
60
+ #
61
+ # +interaction_id+:: The interaction ID for this client's call. This is
62
+ # also sent as an independent, searchable field in
63
+ # the log payload.
64
+ #
65
+ def report( level, component, code, data )
66
+ return if @alchemy.nil? || defined?( Hoodoo::Services::Middleware::AMQPLogMessage ).nil?
67
+
68
+ # Take care with Symbol keys in 'data' vs string keys in e.g. 'Session'.
69
+
70
+ data[ :id ] ||= Hoodoo::UUID.generate()
71
+
72
+ interaction_id = data[ :interaction_id ]
73
+ session = data[ :session ] || {}
74
+
75
+ caller_id = session[ 'caller_id' ]
76
+ identity = ( session[ 'identity' ] || {} ).to_h
77
+
78
+ message = Hoodoo::Services::Middleware::AMQPLogMessage.new(
79
+ :id => data[ :id ],
80
+ :level => level,
81
+ :component => component,
82
+ :code => code,
83
+ :reported_at => Time.now,
84
+
85
+ :data => data,
86
+
87
+ :interaction_id => interaction_id,
88
+ :caller_id => caller_id,
89
+ :identity => identity,
90
+
91
+ :routing_key => @queue_name,
92
+ )
93
+
94
+ # Broken services can attempt to log invalid datatypes such as
95
+ # BigDecimal, which Msgpack can't serialize. At the time of writing,
96
+ # Alchemy AMQ would thus encounter a serialization exception *within
97
+ # its EventMachine sending loop*, so in a different *native* thread.
98
+ # This exception could not be caught by Ruby / Hoodoo in "this"
99
+ # native thread, so instead the uncaught exception kills the service.
100
+ # Although Alchemy could catch that itself, there is no way for it to
101
+ # report the failure to Hoodoo in a way that a log reporting caller
102
+ # could understand; it's async and in the wrong native thread anyway.
103
+ #
104
+ # Solution: In non-production environments only (due to the potential
105
+ # performance hit), manually serialize the message before sending it.
106
+ # If this call blows up, the Hoodoo exception handler will catch it
107
+ # and report the result as a properly formed 500, including the
108
+ # Msgpack (or other exception) details on exactly what was wrong.
109
+ #
110
+ unless Hoodoo::Services::Middleware.environment.production?
111
+ message.serialize()
112
+ end
113
+
114
+ @alchemy.send_message( message )
115
+ end
116
+ end
117
+
118
+ end
119
+ end; end
@@ -0,0 +1,130 @@
1
+ ########################################################################
2
+ # File:: inter_resource_local.rb
3
+ # (C):: Loyalty New Zealand 2014
4
+ #
5
+ # Purpose:: An endpoint that calls back into a known middleware
6
+ # instance to communicate with a resource that is available
7
+ # in the local service application.
8
+ # ----------------------------------------------------------------------
9
+ # 11-Nov-2014 (ADH): Split out from service_middleware.rb
10
+ # 09-Mar-2015 (ADH): Adapted from old endpoint.rb code.
11
+ ########################################################################
12
+
13
+ module Hoodoo; module Services
14
+ class Middleware
15
+
16
+ # This is an endpoint which the middleware uses for inter-resource
17
+ # calls back calling back to that same middleware instance, for
18
+ # resources which exist within the same service application. The
19
+ # middleware manages all the inter-resource preparation and post
20
+ # processing.
21
+ #
22
+ class InterResourceLocal < Hoodoo::Client::Endpoint
23
+
24
+ protected
25
+
26
+ # See Hoodoo::Client::Endpoint#configure_with.
27
+ #
28
+ # It isn't expected that anyone will ever need to use this class
29
+ # beyond Hoodoo::Services::Middleware, but you never know...
30
+ #
31
+ # Configuration option keys which _must_ be supplied are:
32
+ #
33
+ # +interaction+:: A Hoodoo::Services::Middleware::Interaction
34
+ # instance which describes the *source*
35
+ # interaction at hand. This is a middleware
36
+ # concept; the middleware is handling some
37
+ # API call which the source interaction data
38
+ # describes, but the resource which is
39
+ # handling the call needs to make a local
40
+ # inter-resource call, which is why this
41
+ # Endpoint subclass instance is needed.
42
+ #
43
+ # +discovery_result+:: A Hoodoo::Services::Discovery::ForLocal
44
+ # instance describing the locally available
45
+ # resource endpoint.
46
+ #
47
+ def configure_with( resource, version, options )
48
+ @middleware = self.interaction().owning_middleware_instance
49
+ end
50
+
51
+ public
52
+
53
+ # See Hoodoo::Client::Endpoint#list.
54
+ #
55
+ def list( query_hash = nil )
56
+ return @middleware.inter_resource_local(
57
+ :source_interaction => self.interaction(),
58
+ :discovery_result => @discovery_result,
59
+ :endpoint => self,
60
+
61
+ :action => :list,
62
+
63
+ :query_hash => query_hash
64
+ )
65
+ end
66
+
67
+ # See Hoodoo::Client::Endpoint#show.
68
+ #
69
+ def show( ident, query_hash = nil )
70
+ return @middleware.inter_resource_local(
71
+ :source_interaction => self.interaction(),
72
+ :discovery_result => @discovery_result,
73
+ :endpoint => self,
74
+
75
+ :action => :show,
76
+
77
+ :ident => ident,
78
+ :query_hash => query_hash
79
+ )
80
+ end
81
+
82
+ # See Hoodoo::Client::Endpoint#create.
83
+ #
84
+ def create( body_hash, query_hash = nil )
85
+ return @middleware.inter_resource_local(
86
+ :source_interaction => self.interaction(),
87
+ :discovery_result => @discovery_result,
88
+ :endpoint => self,
89
+
90
+ :action => :create,
91
+
92
+ :body_hash => body_hash,
93
+ :query_hash => query_hash
94
+ )
95
+ end
96
+
97
+ # See Hoodoo::Client::Endpoint#update.
98
+ #
99
+ def update( ident, body_hash, query_hash = nil )
100
+ return @middleware.inter_resource_local(
101
+ :source_interaction => self.interaction(),
102
+ :discovery_result => @discovery_result,
103
+ :endpoint => self,
104
+
105
+ :action => :update,
106
+
107
+ :ident => ident,
108
+ :body_hash => body_hash,
109
+ :query_hash => query_hash
110
+ )
111
+ end
112
+
113
+ # See Hoodoo::Client::Endpoint#delete.
114
+ #
115
+ def delete( ident, query_hash = nil )
116
+ return @middleware.inter_resource_local(
117
+ :source_interaction => self.interaction(),
118
+ :discovery_result => @discovery_result,
119
+ :endpoint => self,
120
+
121
+ :action => :delete,
122
+
123
+ :ident => ident,
124
+ :query_hash => query_hash
125
+ )
126
+ end
127
+ end
128
+
129
+ end
130
+ end; end
@@ -0,0 +1,202 @@
1
+ ########################################################################
2
+ # File:: inter_resource_remote.rb
3
+ # (C):: Loyalty New Zealand 2015
4
+ #
5
+ # Purpose:: Resource endpoint definition.
6
+ # ----------------------------------------------------------------------
7
+ # 05-Mar-2015 (ADH): Created.
8
+ ########################################################################
9
+
10
+ module Hoodoo
11
+ module Services
12
+ class Middleware # Just used as a namespace here
13
+
14
+ # This is an endpoint which the middleware uses for inter-resource
15
+ # calls over another 'wrapped' endpoint. This endpoint manages all
16
+ # the inter-resource preparation and post processing, but calls in
17
+ # to another wrapped endpoint to actually talk to the resource for
18
+ # which the inter-resource call is being made.
19
+ #
20
+ # Since it wraps another endpoint, instantiation requirements are
21
+ # rather unusual - see #configure_with for details.
22
+ #
23
+ class InterResourceRemote < Hoodoo::Client::Endpoint
24
+
25
+ protected
26
+
27
+ # See Hoodoo::Client::Endpoint#configure_with.
28
+ #
29
+ # It isn't expected that anyone will ever need to use this class
30
+ # beyond Hoodoo::Services::Middleware, but you never know...
31
+ #
32
+ # Configuration option keys which _must_ be supplied are:
33
+ #
34
+ # +interaction+:: A Hoodoo::Services::Middleware::Interaction
35
+ # instance which describes the *source*
36
+ # interaction at hand. This is a middleware
37
+ # concept; the middleware is handling some
38
+ # API call which the source interaction data
39
+ # describes, but the resource which is
40
+ # handling the call needs to make a remote
41
+ # inter-resource call, which is why this
42
+ # Endpoint subclass instance is needed.
43
+ #
44
+ # +discovery_result+:: A Hoodoo::Services::Discovery::ForRemote
45
+ # instance describing the remotely available
46
+ # resource endpoint.
47
+ #
48
+ # The pattern for creating and using this instance is:
49
+ #
50
+ # * Use the discovery result to build an appropriate Endpoint
51
+ # subclass instance, e.g. Hoodoo::Client::Endpoint::HTTP.
52
+ #
53
+ # * Create a Hoodoo::Services::Discovery::ForRemote instance
54
+ # which describes the above endpoint via the +wrapped_endpoint+
55
+ # option.
56
+ #
57
+ # * Build an instance of this auto-session Endpoint subclass,
58
+ # giving it the above object as the +discovery_result+.
59
+ #
60
+ # * Use this endpoint in the normal fashion. All the special
61
+ # mechanics of remote inter-resource calling are handled here.
62
+ #
63
+ def configure_with( resource, version, options )
64
+ @wrapped_endpoint = @discovery_result.wrapped_endpoint
65
+ end
66
+
67
+ public
68
+
69
+ # See Hoodoo::Client::Endpoint#list.
70
+ #
71
+ def list( query_hash = nil )
72
+ result = preprocess( :list )
73
+ result = @wrapped_endpoint.list( query_hash ) if result.nil?
74
+ return postprocess( result )
75
+ end
76
+
77
+ # See Hoodoo::Client::Endpoint#show.
78
+ #
79
+ def show( ident, query_hash = nil )
80
+ result = preprocess( :show )
81
+ result = @wrapped_endpoint.show( ident, query_hash ) if result.nil?
82
+ return postprocess( result )
83
+ end
84
+
85
+ # See Hoodoo::Client::Endpoint#create.
86
+ #
87
+ def create( body_hash, query_hash = nil )
88
+ result = preprocess( :create )
89
+ result = @wrapped_endpoint.create( body_hash, query_hash ) if result.nil?
90
+ return postprocess( result )
91
+ end
92
+
93
+ # See Hoodoo::Client::Endpoint#update.
94
+ #
95
+ def update( ident, body_hash, query_hash = nil )
96
+ result = preprocess( :update )
97
+ result = @wrapped_endpoint.update( ident, body_hash, query_hash ) if result.nil?
98
+ return postprocess( result )
99
+ end
100
+
101
+ # See Hoodoo::Client::Endpoint#delete.
102
+ #
103
+ def delete( ident, query_hash = nil )
104
+ result = preprocess( :delete )
105
+ result = @wrapped_endpoint.delete( ident, query_hash ) if result.nil?
106
+ return postprocess( result )
107
+ end
108
+
109
+ private
110
+
111
+ # Preprocess the given action. This, for example, includes setting
112
+ # up a session with extra permissions requested by the *calling*
113
+ # resource implementation's interface, if necessary.
114
+ #
115
+ # +action+:: A Hoodoo::Services::Middleware::ALLOWED_ACTIONS entry.
116
+ #
117
+ def preprocess( action )
118
+
119
+ copy_updated_options_to( @wrapped_endpoint )
120
+
121
+ # Interaction ID comes from Endpoint superclass.
122
+ #
123
+ session = self.interaction().context.session
124
+
125
+ unless session.nil? || self.interaction().using_test_session?
126
+ session = session.augment_with_permissions_for( self.interaction() )
127
+ end
128
+
129
+ if session == false
130
+ data = response_class_for( action ).new
131
+ data.platform_errors.add_error( 'platform.invalid_session' )
132
+ return data
133
+ else
134
+
135
+ # We only get away with @wrapping_session as an instance
136
+ # variable because endpoints are not intended to be thread
137
+ # safe, so we assume that only one thread at any given time
138
+ # will be running through "this" instance.
139
+ #
140
+ # We only store the full session rather than just the ID so
141
+ # that we can easily delete it. The inbound session which
142
+ # may have been augmented, would already have any relevant
143
+ # configuration data associated with it - so we don't want
144
+ # to lose that reference by only storing the ID. This would
145
+ # make it very hard / impossible to delete the session again
146
+ # in #postprocess, which could represent a security issue as
147
+ # an elevated permission session could be left kicking
148
+ # around somewhere.
149
+
150
+ @wrapping_session = session
151
+ @wrapped_endpoint.session_id = session.session_id
152
+ return nil
153
+ end
154
+ end
155
+
156
+ # Postprocess the given action. This, for example, includes
157
+ # removing any session with extra permissions that might have been
158
+ # set up in #preprocess.
159
+ #
160
+ # +action+:: A Hoodoo::Client::AugmentedHash or
161
+ # Hoodoo::Client::AugmentedArray containing the result
162
+ # of a previous (successful or unsuccessful) call to a
163
+ # remote target resource. It may be modified.
164
+ #
165
+ def postprocess( result )
166
+
167
+ # Interaction ID comes from Endpoint superclass.
168
+ #
169
+ if @wrapping_session &&
170
+ self.interaction().context &&
171
+ self.interaction().context.session &&
172
+ @wrapping_session.session_id != self.interaction().context.session.session_id
173
+
174
+ # Ignore errors, there's nothing much we can do about them and in
175
+ # the worst case we just have to wait for this to expire naturally.
176
+
177
+ @wrapped_endpoint.session_id = nil
178
+
179
+ session = @wrapping_session
180
+ @wrapping_session = nil
181
+ session.delete_from_memcached()
182
+ end
183
+
184
+ annotate_errors_from_other_resource_in( result )
185
+
186
+ return result
187
+ end
188
+
189
+ # TODO
190
+ #
191
+ def annotate_errors_from_other_resource_in( augmented_thing )
192
+ # TODO - this probably needs to live somewhere else so the
193
+ # endpoint and middleware local service call can 'reach' it.
194
+ # Run through errors, if any; prefix messages with target resource
195
+ # and version; maybe source resource and version too; e.g.:
196
+ # "In v1 of Bar while handling <action> in v2 of Foo: ..."
197
+ end
198
+
199
+ end
200
+ end
201
+ end
202
+ end