hoodoo 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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