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,1014 @@
1
+ # These tests focus on the way that a resource can declare a requirement
2
+ # to gain extra permissions while processing an action, that allow it to
3
+ # call other services. The caller's inbound session only needs to be able
4
+ # to call the 'otuermost' action to succeed.
5
+ #
6
+ # Mock Memcached is used for 'real' (nearly) session management in Hoodoo
7
+ # rather than rely on the allow-all test session. If we used the test
8
+ # session, we'd never test permissions augmentation as it is bypassed in
9
+ # that mode.
10
+ #
11
+ # All the groundwork having been done for permissions testing, this is is
12
+ # also a good place to make sure that interaction IDs are properly passed
13
+ # between both local and remote inter-resource calls, so that's tested in
14
+ # passing here too (there was once a bug where this got broken for local
15
+ # inter-resource calls).
16
+
17
+ require 'spec_helper'
18
+
19
+ # To show Clock, Clock must call Date which must call Time.
20
+ #
21
+ # (1) These are all in the same app (local inter-resource calls)
22
+ # (2) These are each in different apps (remote calls)
23
+ #
24
+ # Then insofar as possible, (1) and (2) with:
25
+ #
26
+ # (A) Clock does not request permission for Date
27
+ # - verify that show yields forbidden and date/time not called
28
+ # - grant session permission for date and verify forbidden
29
+ # and time not called
30
+ # - grant permissions through to time and verify 200
31
+ #
32
+ # (B) Date does not request permission for Time
33
+ # - verify that show yields forbidden, date called, time not
34
+ # - grant permission for time and verify 200
35
+ #
36
+ # (C) Full request from Date to Time
37
+ # - verify that show yields 200, date and time called
38
+ # - use ASK rather than ALLOW for Date -> Time to test #verify
39
+ #
40
+ # Because we don't want same-named resources or same-path resources
41
+ # running concurrently (that counts as platform misconfiguration),
42
+ # we end up with:
43
+ #
44
+ # * Three Clock resource names and endpoints - for with-no-added-permissions
45
+ # calls no-added-Date calls Time; with-permissions calls no-added-Date
46
+ # calls Time; and with-permissions calls with-added-Date calls Time.
47
+ #
48
+ # * Thus two Date names and endpoints - with-permissions calls Time and
49
+ # without-permissions calls Time.
50
+ #
51
+ # * Just one Time resource end endpoint.
52
+
53
+ ##############################################################################
54
+ # Implementations
55
+ ##############################################################################
56
+
57
+ class RSpecAddPermTestClockCallsDateNoPermsImplementation < Hoodoo::Services::Implementation
58
+ def show( context )
59
+ date_time = context.resource( :RSpecAddPermTestDateNoPerms ).show( 'now' )
60
+ return if date_time.adds_errors_to?( context.response.errors )
61
+ context.response.set_resource( date_time )
62
+ end
63
+ end
64
+
65
+ class RSpecAddPermTestClockImplementation < Hoodoo::Services::Implementation
66
+
67
+ # We'll give the top-level Clock a #show and #list action that basically
68
+ # do the same thing. But in the Clock *interface*, we're only going to
69
+ # ask for additional permissions to call Date for the #show action. Thus,
70
+ # attempts to call #list will fail, unless the top-level session already
71
+ # has permission to call Date.
72
+ #
73
+ # Further, #show can be made to call #list and it *does* ask for the
74
+ # permission to do this. So while #list here does not ask for permission
75
+ # for #show "there", #show here *does* ask for permission for #list
76
+ # "there". Thus we test - an action here fails to get permission for a
77
+ # different-named action downstream; an action here does get permission
78
+ # for a different-named action downstream.
79
+
80
+ def show( context )
81
+ if context.request.ident == 'list_instead'
82
+ date_time = context.resource( :RSpecAddPermTestDate ).list()
83
+ else
84
+ date_time = context.resource( :RSpecAddPermTestDate ).show( 'now' )
85
+ end
86
+
87
+ return if date_time.adds_errors_to?( context.response.errors )
88
+ context.response.set_resource( date_time )
89
+ end
90
+
91
+ def list( context )
92
+ date_time = context.resource( :RSpecAddPermTestDate ).show( 'now' )
93
+ return if date_time.adds_errors_to?( context.response.errors )
94
+ context.response.set_resources( [ date_time ] )
95
+ end
96
+ end
97
+
98
+ class RSpecAddPermTestDateImplementation < Hoodoo::Services::Implementation
99
+ def show( context )
100
+ time = context.resource( :RSpecAddPermTestTime ).show( 'now' )
101
+ return if time.adds_errors_to?( context.response.errors )
102
+ context.response.set_resource( { 'date' => '1999-12-31', 'time' => time[ 'time' ] } )
103
+ end
104
+
105
+ def list( context )
106
+ time = context.resource( :RSpecAddPermTestTime ).show( 'now' )
107
+ return if time.adds_errors_to?( context.response.errors )
108
+ context.response.set_resources( [ { 'date' => '1999-12-31', 'time' => time[ 'time' ] } ] )
109
+ end
110
+ end
111
+
112
+ class RSpecAddPermTestTimeImplementation < Hoodoo::Services::Implementation
113
+ def show( context )
114
+ context.response.set_resource( { 'time' => '23:59:59' } )
115
+ end
116
+
117
+ # Using ASK in the interfaces later for this specific case lets us check
118
+ # in tests that the interface's permissions we used when getting through
119
+ # to this implementation, rather than some other route. We have to be
120
+ # expecting #verify and return ALLOW. If we aren't expecting it but it's
121
+ # called anyway, it denis the request to hopefully provoke a test failure.
122
+ #
123
+ # Yes, DENY is the default superclass implementation anyway but explicit
124
+ # code here lets future maintainers read this and know what's happening!
125
+ #
126
+ def verify( context, action )
127
+ Hoodoo::Services::Permissions::DENY
128
+ end
129
+ end
130
+
131
+ # The Interaction ID test "source" (calls to) and "destination" (called
132
+ # by) classes.
133
+
134
+ class RSpecTestInteractionIDPassingDestinationImplementation < Hoodoo::Services::Implementation
135
+ def show( context )
136
+ context.response.set_resource( { 'interaction_id' => context.owning_interaction.interaction_id } )
137
+ end
138
+ end
139
+
140
+ class RSpecTestInteractionIDPassingSourceImplementation < Hoodoo::Services::Implementation
141
+ def show( context )
142
+ destination = context.resource( :RSpecTestInteractionIDPassingDestination )
143
+
144
+ result = destination.show( context.request.ident )
145
+ return if result.adds_errors_to?( context.response.errors )
146
+
147
+ context.response.set_resource( result )
148
+ end
149
+ end
150
+
151
+ ##############################################################################
152
+ # Interfaces
153
+ ##############################################################################
154
+
155
+ class RSpecAddPermTestClockNoPermsCallsDateNoPermsInterface < Hoodoo::Services::Interface
156
+ interface :RSpecAddPermTestClockNoPermsCallsDateNoPerms do
157
+ endpoint :rspec_add_perm_test_clock_no_perms_calls_date_no_perms, RSpecAddPermTestClockCallsDateNoPermsImplementation
158
+ actions :show
159
+ end
160
+ end
161
+
162
+ class RSpecAddPermTestClockCallsDateNoPermsInterface < Hoodoo::Services::Interface
163
+ interface :RSpecAddPermTestClockCallsDateNoPerms do
164
+ endpoint :rspec_add_perm_test_clock_calls_date_no_perms, RSpecAddPermTestClockCallsDateNoPermsImplementation
165
+ actions :show
166
+
167
+ additional_permissions_for( :show ) do | p |
168
+ p.set_resource( :RSpecAddPermTestDateNoPerms, :show, Hoodoo::Services::Permissions::ALLOW )
169
+ end
170
+ end
171
+ end
172
+
173
+ class RSpecAddPermTestClockInterface < Hoodoo::Services::Interface
174
+ interface :RSpecAddPermTestClock do
175
+ endpoint :rspec_add_perm_test_clocks, RSpecAddPermTestClockImplementation
176
+ actions :show, :list
177
+
178
+ additional_permissions_for( :show ) do | p |
179
+ p.set_resource( :RSpecAddPermTestDate, :show, Hoodoo::Services::Permissions::ALLOW )
180
+ p.set_resource( :RSpecAddPermTestDate, :list, Hoodoo::Services::Permissions::ALLOW )
181
+ end
182
+ end
183
+ end
184
+
185
+ class RSpecAddPermTestDateNoPermsInterface < Hoodoo::Services::Interface
186
+ interface :RSpecAddPermTestDateNoPerms do
187
+ endpoint :rspec_add_perm_test_date_no_perms, RSpecAddPermTestDateImplementation
188
+ actions :show
189
+ end
190
+ end
191
+
192
+ class RSpecAddPermTestDateInterface < Hoodoo::Services::Interface
193
+ interface :RSpecAddPermTestDate do
194
+ endpoint :dates, RSpecAddPermTestDateImplementation
195
+ actions :show, :list
196
+
197
+ additional_permissions_for( :show ) do | p |
198
+ p.set_resource( :RSpecAddPermTestTime, :show, Hoodoo::Services::Permissions::ASK )
199
+ end
200
+
201
+ additional_permissions_for( :list ) do | p |
202
+ p.set_resource( :RSpecAddPermTestTime, :show, Hoodoo::Services::Permissions::ASK )
203
+ end
204
+ end
205
+ end
206
+
207
+ class RSpecAddPermTestTimeInterface < Hoodoo::Services::Interface
208
+ interface :RSpecAddPermTestTime do
209
+ endpoint :rspec_add_perm_test_times, RSpecAddPermTestTimeImplementation
210
+ actions :show
211
+ end
212
+ end
213
+
214
+ class RSpecTestInteractionIDPassingDestinationInterface < Hoodoo::Services::Interface
215
+ interface :RSpecTestInteractionIDPassingDestination do
216
+ endpoint :id_passing_destination, RSpecTestInteractionIDPassingDestinationImplementation
217
+ actions :show
218
+ end
219
+ end
220
+
221
+ class RSpecTestInteractionIDPassingSourceInterface < Hoodoo::Services::Interface
222
+ interface :RSpecTestInteractionIDPassingSource do
223
+ endpoint :id_passing_source, RSpecTestInteractionIDPassingSourceImplementation
224
+ actions :show
225
+ additional_permissions_for( :show ) do | p |
226
+ p.set_resource( :RSpecTestInteractionIDPassingDestination, :show, Hoodoo::Services::Permissions::ALLOW )
227
+ end
228
+ end
229
+ end
230
+
231
+ ##############################################################################
232
+ # Service applications for local inter-resource calls
233
+ ##############################################################################
234
+
235
+ # (See earlier) (A) Clock does not request permission for Date
236
+
237
+ class RSpecAddPermTestClockServiceA < Hoodoo::Services::Service
238
+ comprised_of RSpecAddPermTestClockNoPermsCallsDateNoPermsInterface,
239
+ RSpecAddPermTestDateNoPermsInterface,
240
+ RSpecAddPermTestTimeInterface
241
+ end
242
+
243
+ # (See earlier) (B) Date does not request permission for Time
244
+
245
+ class RSpecAddPermTestClockServiceB < Hoodoo::Services::Service
246
+ comprised_of RSpecAddPermTestClockCallsDateNoPermsInterface,
247
+ RSpecAddPermTestDateNoPermsInterface,
248
+ RSpecAddPermTestTimeInterface
249
+ end
250
+
251
+ # (See earlier) (C) Full request from Date to Time
252
+
253
+ class RSpecAddPermTestClockServiceC < Hoodoo::Services::Service
254
+ comprised_of RSpecAddPermTestClockInterface,
255
+ RSpecAddPermTestDateInterface,
256
+ RSpecAddPermTestTimeInterface
257
+ end
258
+
259
+ # (See earlier) Interaction ID test
260
+
261
+ class RSpecTestInteractionIDPassingService < Hoodoo::Services::Service
262
+ comprised_of RSpecTestInteractionIDPassingSourceInterface,
263
+ RSpecTestInteractionIDPassingDestinationInterface
264
+ end
265
+
266
+ ##############################################################################
267
+ # Service applications for remote inter-resource calls
268
+ ##############################################################################
269
+
270
+ class RSpecAddPermTestClockNoPermsCallsDateNoPermsService < Hoodoo::Services::Service
271
+ comprised_of RSpecAddPermTestClockNoPermsCallsDateNoPermsInterface
272
+ end
273
+
274
+ class RSpecAddPermTestClockCallsDateNoPermsService < Hoodoo::Services::Service
275
+ comprised_of RSpecAddPermTestClockCallsDateNoPermsInterface
276
+ end
277
+
278
+ class RSpecAddPermTestClockService < Hoodoo::Services::Service
279
+ comprised_of RSpecAddPermTestClockInterface
280
+ end
281
+
282
+ class RSpecAddPermTestDateNoPermsService < Hoodoo::Services::Service
283
+ comprised_of RSpecAddPermTestDateNoPermsInterface
284
+ end
285
+
286
+ class RSpecAddPermTestDateService < Hoodoo::Services::Service
287
+ comprised_of RSpecAddPermTestDateInterface
288
+ end
289
+
290
+ class RSpecAddPermTestTimeService < Hoodoo::Services::Service
291
+ comprised_of RSpecAddPermTestTimeInterface
292
+ end
293
+
294
+ class RSpecTestInteractionIDPassingDestinationService < Hoodoo::Services::Service
295
+ comprised_of RSpecTestInteractionIDPassingDestinationInterface
296
+ end
297
+
298
+ class RSpecTestInteractionIDPassingSourceService < Hoodoo::Services::Service
299
+ comprised_of RSpecTestInteractionIDPassingSourceInterface
300
+ end
301
+
302
+ ##############################################################################
303
+
304
+ describe Hoodoo::Services::Middleware do
305
+
306
+ before :each do
307
+ @session_id = Hoodoo::UUID.generate
308
+ @caller_id = Hoodoo::UUID.generate
309
+ @caller_version = 1
310
+ @session = Hoodoo::Services::Session.new( {
311
+ :session_id => @session_id,
312
+ :memcached_host => '0.0.0.0:0',
313
+ :caller_id => @caller_id,
314
+ :caller_version => @caller_version
315
+ } )
316
+
317
+ # Grant top-level access to all of the Clock endpoints
318
+
319
+ @session.permissions = Hoodoo::Services::Permissions.new
320
+ @session.permissions.set_resource(
321
+ :RSpecAddPermTestClockNoPermsCallsDateNoPerms,
322
+ :show,
323
+ Hoodoo::Services::Permissions::ALLOW
324
+ )
325
+ @session.permissions.set_resource(
326
+ :RSpecAddPermTestClockCallsDateNoPerms,
327
+ :show,
328
+ Hoodoo::Services::Permissions::ALLOW
329
+ )
330
+ @session.permissions.set_resource(
331
+ :RSpecAddPermTestClock,
332
+ :show,
333
+ Hoodoo::Services::Permissions::ALLOW
334
+ )
335
+ @session.permissions.set_resource(
336
+ :RSpecAddPermTestClock,
337
+ :list,
338
+ Hoodoo::Services::Permissions::ALLOW
339
+ )
340
+ @session.permissions.set_resource(
341
+ :RSpecTestInteractionIDPassingSource,
342
+ :show,
343
+ Hoodoo::Services::Permissions::ALLOW
344
+ )
345
+
346
+ Hoodoo::Services::Session::MockDalliClient.reset()
347
+
348
+ result = @session.save_to_memcached
349
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
350
+ end
351
+
352
+ after :each do
353
+ Hoodoo::Services::Session::MockDalliClient.reset()
354
+ end
355
+
356
+ ############################################################################
357
+ # Local inter-resource calls
358
+ ############################################################################
359
+
360
+ context 'with local resources and' do
361
+
362
+ after :all do
363
+ Hoodoo::Services::Middleware.flush_services_for_test()
364
+ end
365
+
366
+ context 'Clock with no extra permissions for Date or Time' do
367
+ def app
368
+ Rack::Builder.new do
369
+ use Hoodoo::Services::Middleware
370
+ run RSpecAddPermTestClockServiceA.new
371
+ end
372
+ end
373
+
374
+ it 'cannot call #show in Date or Time by default' do
375
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
376
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
377
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
378
+
379
+ get '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
380
+ nil,
381
+ {
382
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
383
+ 'HTTP_X_SESSION_ID' => @session.session_id
384
+ }
385
+
386
+ expect( last_response.status ).to eq( 403 )
387
+
388
+ result = JSON.parse( last_response.body )
389
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
390
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
391
+ end
392
+
393
+ it 'cannot call #show in Time if session only grants Date access' do
394
+
395
+ @session.permissions.set_resource(
396
+ :RSpecAddPermTestDateNoPerms,
397
+ :show,
398
+ Hoodoo::Services::Permissions::ALLOW
399
+ )
400
+
401
+ result = @session.save_to_memcached
402
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
403
+
404
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
405
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
406
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
407
+
408
+ get '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
409
+ nil,
410
+ {
411
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
412
+ 'HTTP_X_SESSION_ID' => @session.session_id
413
+ }
414
+
415
+ expect( last_response.status ).to eq( 403 )
416
+
417
+ result = JSON.parse( last_response.body )
418
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
419
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
420
+ end
421
+
422
+ it 'can call #show if session grants Date and Time access' do
423
+ @session.permissions.set_resource(
424
+ :RSpecAddPermTestDateNoPerms,
425
+ :show,
426
+ Hoodoo::Services::Permissions::ALLOW
427
+ )
428
+
429
+ @session.permissions.set_resource(
430
+ :RSpecAddPermTestTime,
431
+ :show,
432
+ Hoodoo::Services::Permissions::ALLOW
433
+ )
434
+
435
+ result = @session.save_to_memcached
436
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
437
+
438
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
439
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
440
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
441
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :verify )
442
+
443
+ get '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
444
+ nil,
445
+ {
446
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
447
+ 'HTTP_X_SESSION_ID' => @session.session_id
448
+ }
449
+
450
+ expect( last_response.status ).to eq( 200 )
451
+
452
+ result = JSON.parse( last_response.body )
453
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
454
+ end
455
+ end
456
+
457
+ context 'Clock with extra permissions for Date but no extra permissions for Time' do
458
+ def app
459
+ Rack::Builder.new do
460
+ use Hoodoo::Services::Middleware
461
+ run RSpecAddPermTestClockServiceB.new
462
+ end
463
+ end
464
+
465
+ it 'cannot call #show in Time by default' do
466
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
467
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
468
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
469
+
470
+ get '/v1/rspec_add_perm_test_clock_calls_date_no_perms/any',
471
+ nil,
472
+ {
473
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
474
+ 'HTTP_X_SESSION_ID' => @session.session_id
475
+ }
476
+
477
+ expect( last_response.status ).to eq( 403 )
478
+
479
+ result = JSON.parse( last_response.body )
480
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
481
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
482
+ end
483
+
484
+ it 'can call #show if session only grants Time access' do
485
+ @session.permissions.set_resource(
486
+ :RSpecAddPermTestTime,
487
+ :show,
488
+ Hoodoo::Services::Permissions::ALLOW
489
+ )
490
+
491
+ result = @session.save_to_memcached
492
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
493
+
494
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
495
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
496
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
497
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :verify )
498
+
499
+ get '/v1/rspec_add_perm_test_clock_calls_date_no_perms/any',
500
+ nil,
501
+ {
502
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
503
+ 'HTTP_X_SESSION_ID' => @session.session_id
504
+ }
505
+
506
+ expect( last_response.status ).to eq( 200 )
507
+
508
+ result = JSON.parse( last_response.body )
509
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
510
+ end
511
+ end
512
+
513
+ context 'Clock with extra permissions for Date and Time' do
514
+ def app
515
+ Rack::Builder.new do
516
+ use Hoodoo::Services::Middleware
517
+ run RSpecAddPermTestClockServiceC.new
518
+ end
519
+ end
520
+
521
+ it 'can call #show without any extra session permissions' do
522
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
523
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
524
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
525
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
526
+
527
+ get '/v1/rspec_add_perm_test_clocks/any',
528
+ nil,
529
+ {
530
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
531
+ 'HTTP_X_SESSION_ID' => @session.session_id
532
+ }
533
+
534
+ expect( last_response.status ).to eq( 200 )
535
+
536
+ result = JSON.parse( last_response.body )
537
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
538
+ end
539
+
540
+ it 'can call special case #show leading to #list downstream without any extra session permissions' do
541
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
542
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :list ).once.and_call_original
543
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
544
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
545
+
546
+ get '/v1/rspec_add_perm_test_clocks/list_instead',
547
+ nil,
548
+ {
549
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
550
+ 'HTTP_X_SESSION_ID' => @session.session_id
551
+ }
552
+
553
+ expect( last_response.status ).to eq( 200 )
554
+
555
+ result = JSON.parse( last_response.body )
556
+ expect( result ).to eq( { '_data' => [ { 'date' => '1999-12-31', 'time' => '23:59:59' } ] } )
557
+ end
558
+
559
+ it 'cannot call #list without any extra session permissions' do
560
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
561
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show ).once.and_call_original
562
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show ).once.and_call_original
563
+
564
+ get '/v1/rspec_add_perm_test_clocks',
565
+ nil,
566
+ {
567
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
568
+ 'HTTP_X_SESSION_ID' => @session.session_id
569
+ }
570
+
571
+ expect( last_response.status ).to eq( 403 )
572
+ end
573
+
574
+ it 'can call #list with one extra session permission' do
575
+ @session.permissions.set_resource(
576
+ :RSpecAddPermTestDate,
577
+ :show,
578
+ Hoodoo::Services::Permissions::ALLOW
579
+ )
580
+
581
+ result = @session.save_to_memcached
582
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
583
+
584
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
585
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
586
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
587
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
588
+
589
+ get '/v1/rspec_add_perm_test_clocks',
590
+ nil,
591
+ {
592
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
593
+ 'HTTP_X_SESSION_ID' => @session.session_id
594
+ }
595
+
596
+ expect( last_response.status ).to eq( 200 )
597
+
598
+ result = JSON.parse( last_response.body )
599
+ expect( result ).to eq( { '_data' => [ { 'date' => '1999-12-31', 'time' => '23:59:59' } ] } )
600
+ end
601
+
602
+ context 'testing for interaction ID passing' do
603
+ def app
604
+ Rack::Builder.new do
605
+ use Hoodoo::Services::Middleware
606
+ run RSpecTestInteractionIDPassingService.new
607
+ end
608
+ end
609
+
610
+ it 'passes the interaction ID' do
611
+ get '/v1/id_passing_source/any',
612
+ nil,
613
+ {
614
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
615
+ 'HTTP_X_SESSION_ID' => @session.session_id
616
+ }
617
+
618
+ expect( last_response.status ).to eq( 200 )
619
+
620
+ result = JSON.parse( last_response.body )
621
+ expect( result[ 'interaction_id' ] ).to_not be_blank
622
+ expect( result[ 'interaction_id' ] ).to eq( last_response.headers[ 'X-Interaction-ID' ] )
623
+ end
624
+ end
625
+
626
+ context 'for code coverage' do
627
+
628
+ # Top-level "augment session failed"
629
+ #
630
+ it 'can deal with inter-resource session errors (1)' do
631
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
632
+ expect_any_instance_of(Hoodoo::Services::Session).to receive( :augment_with_permissions_for ).once.and_return( false )
633
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
634
+
635
+ get '/v1/rspec_add_perm_test_clocks/any',
636
+ nil,
637
+ {
638
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
639
+ 'HTTP_X_SESSION_ID' => @session.session_id
640
+ }
641
+
642
+ expect( last_response.status ).to eq( 401 )
643
+ end
644
+
645
+ # Inside "augment session", attempt to save to Memcached returns 'false'
646
+ #
647
+ it 'can deal with inter-resource session errors (2)' do
648
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
649
+ expect_any_instance_of(Hoodoo::Services::Session).to receive( :save_to_memcached ).once.and_return( :outdated )
650
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
651
+
652
+ get '/v1/rspec_add_perm_test_clocks/any',
653
+ nil,
654
+ {
655
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
656
+ 'HTTP_X_SESSION_ID' => @session.session_id
657
+ }
658
+
659
+ expect( last_response.status ).to eq( 401 )
660
+ end
661
+
662
+ # Inside "augment session", attempt to save to Memcached returns 'nil'
663
+ #
664
+ it 'can deal with inter-resource session errors (3)' do
665
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
666
+ expect_any_instance_of(Hoodoo::Services::Session).to receive( :save_to_memcached ).once.and_return( :fail )
667
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
668
+
669
+ get '/v1/rspec_add_perm_test_clocks/any',
670
+ nil,
671
+ {
672
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
673
+ 'HTTP_X_SESSION_ID' => @session.session_id
674
+ }
675
+
676
+ expect( last_response.status ).to eq( 500 )
677
+
678
+ result = JSON.parse( last_response.body )
679
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.fault' )
680
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Unable to create interim session for inter-resource call from RSpecAddPermTestClock / show' )
681
+ end
682
+
683
+ it 'handles nil permissions' do
684
+ @session.permissions = nil
685
+
686
+ result = @session.save_to_memcached
687
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
688
+
689
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show )
690
+
691
+ get '/v1/rspec_add_perm_test_clocks/any',
692
+ nil,
693
+ {
694
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
695
+ 'HTTP_X_SESSION_ID' => @session.session_id
696
+ }
697
+
698
+ expect( last_response.status ).to eq( 403 )
699
+ end
700
+
701
+ it 'handles empty permissions' do
702
+ @session.permissions = Hoodoo::Services::Permissions.new( {} )
703
+
704
+ result = @session.save_to_memcached
705
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
706
+
707
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show )
708
+
709
+ get '/v1/rspec_add_perm_test_clocks/any',
710
+ nil,
711
+ {
712
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
713
+ 'HTTP_X_SESSION_ID' => @session.session_id
714
+ }
715
+
716
+ expect( last_response.status ).to eq( 403 )
717
+ end
718
+
719
+ it 'handles default #verify response as deny' do
720
+ @session.permissions.set_resource( :RSpecAddPermTestClock, :show, Hoodoo::Services::Permissions::ASK )
721
+
722
+ result = @session.save_to_memcached
723
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
724
+
725
+ expect_any_instance_of(Hoodoo::Services::Implementation).to receive( :verify ).once.and_call_original
726
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to_not receive( :show ).once.and_call_original
727
+
728
+ get '/v1/rspec_add_perm_test_clocks/any',
729
+ nil,
730
+ {
731
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
732
+ 'HTTP_X_SESSION_ID' => @session.session_id
733
+ }
734
+
735
+ expect( last_response.status ).to eq( 403 )
736
+ end
737
+
738
+ it 'handles custom #verify response as deny' do
739
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
740
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
741
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
742
+ # The Time endpoint already returns DENY out-of-the-box.
743
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).once.and_call_original
744
+
745
+ get '/v1/rspec_add_perm_test_clocks/any',
746
+ nil,
747
+ {
748
+ 'CONTENT_TYPE' => 'application/json; charset=utf-8',
749
+ 'HTTP_X_SESSION_ID' => @session.session_id
750
+ }
751
+
752
+ expect( last_response.status ).to eq( 403 )
753
+ end
754
+ end
755
+ end
756
+ end
757
+
758
+ ############################################################################
759
+ # Remote inter-resource calls
760
+ ############################################################################
761
+
762
+ context 'with remote resources and' do
763
+
764
+ before :all do
765
+ @port_clock_no_perms_calls_date_no_perms = spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestClockNoPermsCallsDateNoPermsService )
766
+ @port_clock_calls_date_no_perms = spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestClockCallsDateNoPermsService )
767
+ @port_clock = spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestClockService )
768
+ @port_iid_source = spec_helper_start_svc_app_in_thread_for( RSpecTestInteractionIDPassingSourceService )
769
+
770
+ spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestDateNoPermsService )
771
+ spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestDateService )
772
+ spec_helper_start_svc_app_in_thread_for( RSpecAddPermTestTimeService )
773
+ spec_helper_start_svc_app_in_thread_for( RSpecTestInteractionIDPassingDestinationService )
774
+ end
775
+
776
+ after :all do
777
+ Hoodoo::Services::Middleware.flush_services_for_test()
778
+ end
779
+
780
+ context 'Clock with no extra permissions for Date or Time' do
781
+ it 'cannot call #show in Date or Time by default' do
782
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
783
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
784
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
785
+
786
+ response = spec_helper_http(
787
+ :path => '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
788
+ :port => @port_clock_no_perms_calls_date_no_perms,
789
+ :headers => { 'X-Session-ID' => @session.session_id }
790
+ )
791
+ expect( response.code ).to eq( '403' )
792
+
793
+ result = JSON.parse( response.body )
794
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
795
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
796
+ end
797
+
798
+ it 'cannot call #show in Time if session only grants Date access' do
799
+ @session.permissions.set_resource(
800
+ :RSpecAddPermTestDateNoPerms,
801
+ :show,
802
+ Hoodoo::Services::Permissions::ALLOW
803
+ )
804
+
805
+ result = @session.save_to_memcached
806
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
807
+
808
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
809
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
810
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
811
+
812
+ response = spec_helper_http(
813
+ :path => '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
814
+ :port => @port_clock_no_perms_calls_date_no_perms,
815
+ :headers => { 'X-Session-ID' => @session.session_id }
816
+ )
817
+ expect( response.code ).to eq( '403' )
818
+
819
+ result = JSON.parse( response.body )
820
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
821
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
822
+ end
823
+
824
+ it 'can call #show if session grants Date and Time access' do
825
+ @session.permissions.set_resource(
826
+ :RSpecAddPermTestDateNoPerms,
827
+ :show,
828
+ Hoodoo::Services::Permissions::ALLOW
829
+ )
830
+
831
+ @session.permissions.set_resource(
832
+ :RSpecAddPermTestTime,
833
+ :show,
834
+ Hoodoo::Services::Permissions::ALLOW
835
+ )
836
+
837
+ result = @session.save_to_memcached
838
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
839
+
840
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
841
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
842
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
843
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :verify )
844
+
845
+ response = spec_helper_http(
846
+ :path => '/v1/rspec_add_perm_test_clock_no_perms_calls_date_no_perms/any',
847
+ :port => @port_clock_no_perms_calls_date_no_perms,
848
+ :headers => { 'X-Session-ID' => @session.session_id }
849
+ )
850
+ expect( response.code ).to eq( '200' )
851
+
852
+ result = JSON.parse( response.body )
853
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
854
+ end
855
+ end
856
+
857
+ context 'Clock with extra permissions for Date but no extra permissions for Time' do
858
+ it 'cannot call #show in Time by default' do
859
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
860
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
861
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show )
862
+
863
+ response = spec_helper_http(
864
+ :path => '/v1/rspec_add_perm_test_clock_calls_date_no_perms/any',
865
+ :port => @port_clock_calls_date_no_perms,
866
+ :headers => { 'X-Session-ID' => @session.session_id }
867
+ )
868
+ expect( response.code ).to eq( '403' )
869
+
870
+ result = JSON.parse( response.body )
871
+ expect( result[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
872
+ expect( result[ 'errors' ][ 0 ][ 'message' ] ).to eq( 'Action not authorized' )
873
+ end
874
+
875
+ it 'can call #show if session only grants Time access' do
876
+ @session.permissions.set_resource(
877
+ :RSpecAddPermTestTime,
878
+ :show,
879
+ Hoodoo::Services::Permissions::ALLOW
880
+ )
881
+
882
+ result = @session.save_to_memcached
883
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
884
+
885
+ expect_any_instance_of(RSpecAddPermTestClockCallsDateNoPermsImplementation).to receive( :show ).once.and_call_original
886
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
887
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
888
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :verify )
889
+
890
+ response = spec_helper_http(
891
+ :path => '/v1/rspec_add_perm_test_clock_calls_date_no_perms/any',
892
+ :port => @port_clock_calls_date_no_perms,
893
+ :headers => { 'X-Session-ID' => @session.session_id }
894
+ )
895
+ expect( response.code ).to eq( '200' )
896
+
897
+ result = JSON.parse( response.body )
898
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
899
+ end
900
+ end
901
+
902
+ context 'Clock with extra permissions for Date and Time' do
903
+ it 'can call #show without any extra session permissions' do
904
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
905
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
906
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
907
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
908
+
909
+ response = spec_helper_http(
910
+ :path => '/v1/rspec_add_perm_test_clocks/any',
911
+ :port => @port_clock,
912
+ :headers => { 'X-Session-ID' => @session.session_id }
913
+ )
914
+ expect( response.code ).to eq( '200' )
915
+
916
+ result = JSON.parse( response.body )
917
+ expect( result ).to eq( { 'date' => '1999-12-31', 'time' => '23:59:59' } )
918
+ end
919
+
920
+ it 'can call special case #show leading to #list downstream without any extra session permissions' do
921
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
922
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :list ).once.and_call_original
923
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
924
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
925
+
926
+ response = spec_helper_http(
927
+ :path => '/v1/rspec_add_perm_test_clocks/list_instead',
928
+ :port => @port_clock,
929
+ :headers => { 'X-Session-ID' => @session.session_id }
930
+ )
931
+ expect( response.code ).to eq( '200' )
932
+
933
+ result = JSON.parse( response.body )
934
+ expect( result ).to eq( { '_data' => [ { 'date' => '1999-12-31', 'time' => '23:59:59' } ] } )
935
+ end
936
+
937
+ it 'cannot call #list without any extra session permissions' do
938
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
939
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show ).once.and_call_original
940
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to_not receive( :show ).once.and_call_original
941
+
942
+ response = spec_helper_http(
943
+ :path => '/v1/rspec_add_perm_test_clocks',
944
+ :port => @port_clock,
945
+ :headers => { 'X-Session-ID' => @session.session_id }
946
+ )
947
+ expect( response.code ).to eq( '403' )
948
+ end
949
+
950
+ it 'can call #list with one extra session permission' do
951
+ @session.permissions.set_resource(
952
+ :RSpecAddPermTestDate,
953
+ :show,
954
+ Hoodoo::Services::Permissions::ALLOW
955
+ )
956
+
957
+ result = @session.save_to_memcached
958
+ raise "Can't save to mock Memcached (result = #{result})" unless result == :ok
959
+
960
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :list ).once.and_call_original
961
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to receive( :show ).once.and_call_original
962
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :show ).once.and_call_original
963
+ expect_any_instance_of(RSpecAddPermTestTimeImplementation).to receive( :verify ).with( anything(), :show ).and_return( Hoodoo::Services::Permissions::ALLOW )
964
+
965
+ response = spec_helper_http(
966
+ :path => '/v1/rspec_add_perm_test_clocks',
967
+ :port => @port_clock,
968
+ :headers => { 'X-Session-ID' => @session.session_id }
969
+ )
970
+ expect( response.code ).to eq( '200' )
971
+
972
+ result = JSON.parse( response.body )
973
+ expect( result ).to eq( { '_data' => [ { 'date' => '1999-12-31', 'time' => '23:59:59' } ] } )
974
+ end
975
+
976
+ context 'for code coverage' do
977
+
978
+ # Top-level "augment session failed". Failures inside the "augment
979
+ # session" code were tested in the previous section dealing with
980
+ # local inter-resource calls (they use the same back-end method).
981
+ #
982
+ it 'can deal with inter-resource session errors' do
983
+ expect_any_instance_of(RSpecAddPermTestClockImplementation).to receive( :show ).once.and_call_original
984
+ expect_any_instance_of(Hoodoo::Services::Session).to receive( :augment_with_permissions_for ).once.and_return( false )
985
+ expect_any_instance_of(RSpecAddPermTestDateImplementation).to_not receive( :show )
986
+
987
+ response = spec_helper_http(
988
+ :path => '/v1/rspec_add_perm_test_clocks/any',
989
+ :port => @port_clock,
990
+ :headers => { 'X-Session-ID' => @session.session_id }
991
+ )
992
+ expect( response.code ).to eq( '401' )
993
+ end
994
+
995
+ end
996
+ end
997
+
998
+ context 'testing for interaction ID passing' do
999
+ it 'passes the interaction ID' do
1000
+ response = spec_helper_http(
1001
+ :path => '/v1/id_passing_source/any',
1002
+ :port => @port_iid_source,
1003
+ :headers => { 'X-Session-ID' => @session.session_id }
1004
+ )
1005
+ expect( response.code ).to eq( '200' )
1006
+
1007
+ result = JSON.parse( response.body )
1008
+
1009
+ expect( result[ 'interaction_id' ] ).to_not be_blank
1010
+ expect( result[ 'interaction_id' ] ).to eq( response[ 'X-Interaction-ID' ] )
1011
+ end
1012
+ end
1013
+ end
1014
+ end