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,249 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoodoo::Services::Permissions do
4
+ it 'initialises with a "deny" default fallback' do
5
+ p = described_class.new
6
+
7
+ expect( p.to_h ).to eq({
8
+ 'default' => { 'else' => described_class::DENY }
9
+ })
10
+ end
11
+
12
+ it 'sets default fallback' do
13
+ p = described_class.new
14
+
15
+ p.set_default_fallback( described_class::ALLOW )
16
+
17
+ expect( p.to_h ).to eq({
18
+ 'default' => { 'else' => described_class::ALLOW }
19
+ })
20
+ end
21
+
22
+ it 'sets default actions' do
23
+ p = described_class.new
24
+
25
+ p.set_default( 'create', described_class::ALLOW )
26
+ p.set_default( 'update', described_class::ASK )
27
+ p.set_default( 'delete', described_class::DENY )
28
+
29
+ expect( p.to_h ).to eq({
30
+ 'default' => {
31
+ 'actions' => {
32
+ 'create' => described_class::ALLOW,
33
+ 'update' => described_class::ASK,
34
+ 'delete' => described_class::DENY
35
+ },
36
+ 'else' => described_class::DENY
37
+ }
38
+ })
39
+ end
40
+
41
+ it 'sets resource fallback' do
42
+ p = described_class.new
43
+
44
+ p.set_resource_fallback( :Foo, described_class::ALLOW )
45
+ p.set_resource_fallback( :Bar, described_class::ASK )
46
+
47
+ expect( p.to_h ).to eq({
48
+ 'default' => {
49
+ 'else' => described_class::DENY
50
+ },
51
+ 'resources' => {
52
+ 'Foo' => {
53
+ 'else' => described_class::ALLOW
54
+ },
55
+ 'Bar' => {
56
+ 'else' => described_class::ASK
57
+ }
58
+ }
59
+ })
60
+ end
61
+
62
+ it 'set resource actions' do
63
+ p = described_class.new
64
+
65
+ p.set_resource( :Foo, 'create', described_class::ALLOW )
66
+ p.set_resource( :Foo, 'update', described_class::ASK )
67
+
68
+ p.set_resource_fallback( :Foo, described_class::ALLOW )
69
+
70
+ p.set_resource( :Bar, 'show', described_class::DENY )
71
+ p.set_resource( :Bar, 'delete', described_class::ALLOW )
72
+
73
+ expect( p.to_h ).to eq({
74
+ 'default' => {
75
+ 'else' => described_class::DENY
76
+ },
77
+ 'resources' => {
78
+ 'Foo' => {
79
+ 'actions' => {
80
+ 'create' => described_class::ALLOW,
81
+ 'update' => described_class::ASK
82
+ },
83
+ 'else' => described_class::ALLOW
84
+ },
85
+ 'Bar' => {
86
+ 'actions' => {
87
+ 'show' => described_class::DENY,
88
+ 'delete' => described_class::ALLOW
89
+ }
90
+ }
91
+ }
92
+ })
93
+ end
94
+
95
+ context 'with a resource but no resource fallback' do
96
+ before :each do
97
+ @p = described_class.new
98
+
99
+ @p.set_default_fallback( described_class::ASK )
100
+
101
+ @p.set_resource( :Foo, 'create', described_class::ALLOW )
102
+ @p.set_resource( :Foo, 'update', described_class::ASK )
103
+ @p.set_resource( :Foo, 'delete', described_class::DENY )
104
+
105
+ @expected = {
106
+ 'resources' => {
107
+ 'Foo' => {
108
+ 'actions' => {
109
+ 'create' => described_class::ALLOW,
110
+ 'update' => described_class::ASK,
111
+ 'delete' => described_class::DENY
112
+ }
113
+ },
114
+ },
115
+ 'default' => {
116
+ 'else' => described_class::ASK
117
+ }
118
+ }
119
+ end
120
+
121
+ it 'can be used to initialise a new instance as a Hash' do
122
+ p = described_class.new( @p.to_h )
123
+ expect( p.to_h ).to eq( @expected )
124
+ end
125
+
126
+ it 'behaves correctly' do
127
+ expect( @p.permitted?( :Foo, :create ) ).to eq( described_class::ALLOW )
128
+ expect( @p.permitted?( :Foo, :show ) ).to eq( described_class::ASK )
129
+ expect( @p.permitted?( :Foo, :list ) ).to eq( described_class::ASK )
130
+ expect( @p.permitted?( :Foo, :update ) ).to eq( described_class::ASK )
131
+ expect( @p.permitted?( :Foo, :delete ) ).to eq( described_class::DENY )
132
+ end
133
+ end
134
+
135
+ context 'with permissions set' do
136
+ before :each do
137
+ @p = described_class.new
138
+
139
+ @p.set_default_fallback( described_class::DENY )
140
+
141
+ @p.set_default( 'create', described_class::ASK )
142
+ @p.set_default( 'update', described_class::DENY )
143
+ @p.set_default( 'delete', described_class::ALLOW )
144
+
145
+ @p.set_resource( :Foo, 'create', described_class::ALLOW )
146
+ @p.set_resource( :Foo, 'update', described_class::ASK )
147
+ @p.set_resource( :Foo, 'delete', described_class::DENY )
148
+
149
+ @p.set_resource_fallback( :Foo, described_class::ALLOW )
150
+
151
+ @expected = {
152
+ 'resources' => {
153
+ 'Foo' => {
154
+ 'actions' => {
155
+ 'create' => described_class::ALLOW,
156
+ 'update' => described_class::ASK,
157
+ 'delete' => described_class::DENY
158
+ },
159
+ 'else' => described_class::ALLOW
160
+ },
161
+ },
162
+ 'default' => {
163
+ 'actions' => {
164
+ 'create' => described_class::ASK,
165
+ 'update' => described_class::DENY,
166
+ 'delete' => described_class::ALLOW
167
+ },
168
+ 'else' => described_class::DENY
169
+ }
170
+ }
171
+ end
172
+
173
+ it 'can be loaded into another instance as a Hash' do
174
+ p = described_class.new
175
+ p.from_h!( @p.to_h )
176
+ expect( p.to_h ).to eq( @expected )
177
+ end
178
+
179
+ it 'can be used to initialise a new instance as a Hash' do
180
+ p = described_class.new( @p.to_h )
181
+ expect( p.to_h ).to eq( @expected )
182
+ end
183
+
184
+ it 'merges' do
185
+ p = described_class.new
186
+ p.set_resource_fallback( :Foo, described_class::ASK )
187
+ p.set_default( 'show', described_class::ALLOW )
188
+ p.set_default( 'update', described_class::ALLOW )
189
+ p.set_resource( :Bar, 'show', described_class::ALLOW )
190
+ @p.merge!( p.to_h )
191
+ expect( @p.to_h ).to eq( {
192
+ 'resources' => {
193
+ 'Foo' => {
194
+ 'actions' => {
195
+ 'create' => described_class::ALLOW,
196
+ 'update' => described_class::ASK,
197
+ 'delete' => described_class::DENY
198
+ },
199
+ 'else' => described_class::ASK
200
+ },
201
+ 'Bar' => {
202
+ 'actions' => {
203
+ 'show' => described_class::ALLOW
204
+ }
205
+ }
206
+ },
207
+ 'default' => {
208
+ 'actions' => {
209
+ 'show' => described_class::ALLOW,
210
+ 'create' => described_class::ASK,
211
+ 'update' => described_class::ALLOW,
212
+ 'delete' => described_class::ALLOW
213
+ },
214
+ 'else' => described_class::DENY
215
+ }
216
+ } )
217
+ end
218
+
219
+ it 'allows correctly' do
220
+ expect( @p.permitted?( :Foo, :create ) ).to eq( described_class::ALLOW )
221
+ expect( @p.permitted?( :Foo, :show ) ).to eq( described_class::ALLOW )
222
+ expect( @p.permitted?( :Foo, :list ) ).to eq( described_class::ALLOW )
223
+ end
224
+
225
+ it 'asks correctly' do
226
+ expect( @p.permitted?( :Foo, :update ) ).to eq( described_class::ASK )
227
+ end
228
+
229
+ it 'denies correctly' do
230
+ expect( @p.permitted?( :Foo, :delete ) ).to eq( described_class::DENY )
231
+ end
232
+
233
+ it 'action defaults work' do
234
+ expect( @p.permitted?( :Bar, :create ) ).to eq( described_class::ASK )
235
+ expect( @p.permitted?( :Bar, :update ) ).to eq( described_class::DENY )
236
+ expect( @p.permitted?( :Bar, :delete ) ).to eq( described_class::ALLOW )
237
+ end
238
+
239
+ it 'fallback default works' do
240
+ expect( @p.permitted?( :Bar, :show ) ).to eq( described_class::DENY )
241
+ expect( @p.permitted?( :Bar, :list ) ).to eq( described_class::DENY )
242
+ end
243
+
244
+ it 'empty hashes deny' do
245
+ @p.from_h!( {} )
246
+ expect( @p.permitted?( :Bar, :show ) ).to eq( described_class::DENY )
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoodoo::Services::Request do
4
+ context 'uri_path_components' do
5
+ before do
6
+ @r = Hoodoo::Services::Request.new
7
+ end
8
+
9
+ it 'should record path components properly' do
10
+ ary = [ 'one', 'two', 'three' ]
11
+ @r.uri_path_components = ary
12
+
13
+ expect(@r.uri_path_components).to eq(ary)
14
+ expect(@r.ident).to eq(ary.first)
15
+ end
16
+
17
+ it 'should deal with nil path components properly' do
18
+ ary = nil
19
+ @r.uri_path_components = ary
20
+
21
+ expect(@r.uri_path_components).to be_nil
22
+ expect(@r.ident).to be_nil
23
+ end
24
+
25
+ it 'should deal with non-array path components properly' do
26
+ ary = 'not an array'
27
+ @r.uri_path_components = ary
28
+
29
+ expect(@r.uri_path_components).to be_nil
30
+ expect(@r.ident).to be_nil
31
+ end
32
+
33
+ it 'rationalises date/time' do
34
+ [ :dated_at, :dated_from ].each do | attr |
35
+ now = DateTime.now
36
+ @r.send( "#{ attr }=", now )
37
+ expect( @r.send( attr ) ).to eq( now )
38
+
39
+ now = DateTime.now + 10
40
+ @r.send( "#{ attr }=", now.to_time )
41
+ expect( @r.send( attr ) ).to eq( now )
42
+
43
+ now = DateTime.now + 20
44
+ @r.send( "#{ attr }=", Hoodoo::Utilities::nanosecond_iso8601( now ) )
45
+ expect( @r.send( attr ) ).to eq( now )
46
+ end
47
+ end
48
+
49
+ it 'has correct default values' do
50
+ expect( @r.locale ).to eq( 'en-nz' )
51
+ expect( @r.dated_at ).to eq( nil )
52
+ expect( @r.body ).to eq( nil )
53
+ expect( @r.uri_path_components ).to eq( [] )
54
+ expect( @r.ident ).to eq( nil )
55
+ expect( @r.uri_path_extension ).to eq( '' )
56
+ expect( @r.list.offset ).to eq( 0 )
57
+ expect( @r.list.limit ).to eq( 50 )
58
+ expect( @r.list_sort_data ).to eq( { 'created_at' => 'desc' } )
59
+ expect( @r.list.search_data ).to eq( {} )
60
+ expect( @r.list.filter_data ).to eq( {} )
61
+ expect( @r.embeds ).to eq( [] )
62
+ expect( @r.references ).to eq( [] )
63
+ expect( @r.headers ).to eq( {} )
64
+
65
+ expect( @r.headers.frozen? ).to eq( true )
66
+ end
67
+
68
+ it 'supports deprecated accessors' do
69
+ expect( @r.list_offset ).to eq( 0 )
70
+ expect( @r.list_limit ).to eq( 50 )
71
+ expect( @r.list_sort_data ).to eq( { 'created_at' => 'desc' } )
72
+ expect( @r.list_search_data ).to eq( {} )
73
+ expect( @r.list_filter_data ).to eq( {} )
74
+
75
+ lo = 10
76
+ ll = 20
77
+ ke = 'foo'
78
+ di = 'asc'
79
+ sd = { :foo => :bar }
80
+ fd = { :baz => :foo }
81
+
82
+ @r.list_offset = lo
83
+ @r.list_limit = ll
84
+ @r.list_sort_data = { ke => di }
85
+ @r.list_search_data = sd
86
+ @r.list_filter_data = fd
87
+
88
+ expect( @r.list_offset ).to eq( lo )
89
+ expect( @r.list_limit ).to eq( ll )
90
+ expect( @r.list_sort_data ).to eq( { ke => di } )
91
+ expect( @r.list_search_data ).to eq( sd )
92
+ expect( @r.list_filter_data ).to eq( fd )
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,250 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoodoo::Services::Response do
4
+ before :each do
5
+ @r = Hoodoo::Services::Response.new( Hoodoo::UUID.generate() )
6
+ end
7
+
8
+ it 'should acquire the expected default values when instantiated' do
9
+ expect(@r.errors).to be_a(Hoodoo::Errors)
10
+ expect(@r.errors.has_errors?).to eq(false)
11
+ expect(@r.http_status_code).to eq(200)
12
+ expect(@r.body).to eq({})
13
+ expect(@r.instance_variable_get('@headers')).to eq({})
14
+ end
15
+
16
+ context 'instantiation' do
17
+ it 'rejects a nil interaction ID' do
18
+ expect {
19
+ Hoodoo::Services::Response.new( nil )
20
+ }.to raise_error( RuntimeError, "Hoodoo::Services::Response.new must be given a valid Interaction ID (got 'nil')" )
21
+ end
22
+
23
+ it 'rejects a non-string interaction ID' do
24
+ expect {
25
+ Hoodoo::Services::Response.new( 12345 )
26
+ }.to raise_error( RuntimeError, "Hoodoo::Services::Response.new must be given a valid Interaction ID (got '12345')" )
27
+ end
28
+
29
+ it 'rejects an invalid string interaction ID' do
30
+ expect {
31
+ Hoodoo::Services::Response.new( 'hello' )
32
+ }.to raise_error( RuntimeError, "Hoodoo::Services::Response.new must be given a valid Interaction ID (got '\"hello\"')" )
33
+ end
34
+ end
35
+
36
+ context '#add_error and #halt_processing?' do
37
+ it 'should not say "halt" if there are no errors' do
38
+ expect(@r.errors.has_errors?).to eq(false)
39
+ expect(@r.halt_processing?).to eq(false)
40
+ end
41
+
42
+ it 'should say "halt" if there are errors' do
43
+ @r.add_error('platform.malformed')
44
+ expect(@r.errors.has_errors?).to eq(true)
45
+ expect(@r.halt_processing?).to eq(true)
46
+ end
47
+ end
48
+
49
+ context '#add_errors' do
50
+ it 'should merge errors (1)' do
51
+ e = Hoodoo::Errors.new
52
+ e.add_error( 'platform.malformed' )
53
+ e.add_error( 'generic.malformed' )
54
+
55
+ @r.add_error( 'platform.invalid_session' )
56
+ expect( @r.add_errors( e ) ).to eq( true )
57
+
58
+ expect(@r.errors.errors).to eq([
59
+ { 'code' => 'platform.invalid_session', 'message' => 'Invalid session' },
60
+ { 'code' => 'platform.malformed', 'message' => 'Malformed request' },
61
+ { 'code' => 'generic.malformed', 'message' => 'Malformed payload' }
62
+ ])
63
+
64
+ # Should keep the HTTP status code from the first error added,
65
+ # which was the "invalid session" we added.
66
+
67
+ expect(@r.errors.http_status_code).to eq(401)
68
+ end
69
+
70
+ it 'should merge errors (2)' do
71
+ e = Hoodoo::Errors.new
72
+ e.add_error( 'platform.malformed' )
73
+ e.add_error( 'generic.malformed' )
74
+
75
+ expect( @r.add_errors( e ) ).to eq( true )
76
+ @r.add_error( 'platform.invalid_session' )
77
+
78
+ expect(@r.errors.errors).to eq([
79
+ { 'code' => 'platform.malformed', 'message' => 'Malformed request' },
80
+ { 'code' => 'generic.malformed', 'message' => 'Malformed payload' },
81
+ { 'code' => 'platform.invalid_session', 'message' => 'Invalid session' }
82
+ ])
83
+
84
+ # Should keep the HTTP status code from the first error added,
85
+ # which was the "platform.malformed" from the merged set.
86
+
87
+ expect(@r.errors.http_status_code).to eq(422)
88
+ end
89
+
90
+ it 'should "merge" empty errors' do
91
+ e = Hoodoo::Errors.new
92
+
93
+ expect( @r.add_errors( e ) ).to eq( false )
94
+ @r.add_error( 'platform.invalid_session' )
95
+
96
+ expect(@r.errors.errors).to eq([
97
+ { 'code' => 'platform.invalid_session', 'message' => 'Invalid session' }
98
+ ])
99
+
100
+ # Should keep the HTTP status code from the first error added,
101
+ # which was the "platform.malformed" from the merged set.
102
+
103
+ expect(@r.errors.http_status_code).to eq(401)
104
+ end
105
+ end
106
+
107
+ context '#add_precompiled_error' do
108
+ it 'should let me add precompiled errors' do
109
+ expect {
110
+ @r.add_precompiled_error('test_domain.http_345_no_references 1', 'message 1', 'baz, foo 1')
111
+ @r.add_precompiled_error('test_domain.http_345_no_references 2', 'message 2', 'baz, foo 2')
112
+ @r.add_precompiled_error('test_domain.http_345_no_references 3', 'message 3', 'baz, foo 3')
113
+ }.to_not raise_error
114
+
115
+ expect(@r.errors.errors[0]).to eq({'code' => 'test_domain.http_345_no_references 1', 'message' => 'message 1', 'reference' => 'baz, foo 1'})
116
+ expect(@r.errors.errors[1]).to eq({'code' => 'test_domain.http_345_no_references 2', 'message' => 'message 2', 'reference' => 'baz, foo 2'})
117
+ expect(@r.errors.errors[2]).to eq({'code' => 'test_domain.http_345_no_references 3', 'message' => 'message 3', 'reference' => 'baz, foo 3'})
118
+ end
119
+ end
120
+
121
+ context '#add_header, #get_header and #headers' do
122
+ it 'should let me add headers' do
123
+ @r.add_header( 'X-Foo', 'baz' )
124
+ @r.add_header( 'X-Bar', 'boo' )
125
+
126
+ expect(@r.get_header('X-Foo')).to eq('baz')
127
+ expect(@r.get_header('X-FOO')).to eq('baz')
128
+ expect(@r.get_header('x-foo')).to eq('baz')
129
+ expect(@r.get_header('x-baR')).to eq('boo')
130
+ expect(@r.get_header('random')).to eq(nil)
131
+ end
132
+
133
+ it 'should list headers' do
134
+ @r.add_header( 'X-Foo', 'baz' )
135
+ @r.add_header( 'x-bar', 'boo' )
136
+ @r.add_header( 'X-BAZ', 'bin' )
137
+
138
+ expect(@r.headers).to eq({'X-Foo' => 'baz', 'x-bar' => 'boo', 'X-BAZ' => 'bin'})
139
+ end
140
+
141
+ it 'should complain if I try to set the same header twice without the overwrite flag set' do
142
+ @r.add_header( 'X-Foo', 'baz' )
143
+ expect {
144
+ @r.add_header( 'x-fOO', 'thing' )
145
+ }.to raise_error(RuntimeError, "Hoodoo::Services::Response\#add_header: Value 'baz' already defined for header 'X-Foo'")
146
+ end
147
+
148
+ it 'should allow me to overwrite a header value' do
149
+ @r.add_header( 'X-Foo', 'baz' )
150
+ @r.add_header( 'x-fOO', 'thing', true )
151
+ expect(@r.get_header('x-foo')).to eq('thing')
152
+ end
153
+ end
154
+
155
+ context '#for_rack' do
156
+
157
+ it 'should return default empty data correctly' do
158
+ status, headers, body = @r.for_rack
159
+
160
+ expected = JSON.generate({})
161
+ expect(status).to eq(200)
162
+ expect(headers).to eq({'Content-Length' => expected.length.to_s})
163
+ expect(body.body).to eq([expected])
164
+ end
165
+
166
+ it 'should return header data correctly' do
167
+ @r.add_header( 'X-Foo', :baz )
168
+ @r.add_header( :'X-Bar', 'boo' )
169
+
170
+ status, headers, body = @r.for_rack
171
+
172
+ expected = JSON.generate({})
173
+ expect(status).to eq(200)
174
+ expect(headers).to eq({'X-Foo' => 'baz', 'X-Bar' => 'boo', 'Content-Length' => expected.length.to_s})
175
+ expect(body.body).to eq([expected])
176
+ end
177
+
178
+ it 'should return error condition Rack data correctly' do
179
+ @r.add_error('platform.malformed') # 422 status
180
+ @r.add_error('platform.not_found', 'reference' => {:entity_name => 'hello'}) # 404 status
181
+
182
+ @r.body = { this: 'should be ignored' }
183
+
184
+ errors_hash = @r.errors.render(@r.instance_variable_get('@interaction_id'))
185
+ status, headers, body = @r.for_rack
186
+
187
+ expected = JSON.generate(errors_hash)
188
+ expect(status).to eq(422) # From the first error we stored, not the second
189
+ expect(headers).to eq({'Content-Length' => expected.length.to_s})
190
+ expect(body.body).to eq([expected])
191
+ end
192
+
193
+ it 'should return non-error condition Rack data correctly with a Hash body' do
194
+ response_hash = { this: 'should not be ignored' }
195
+ @r.body = response_hash
196
+
197
+ status, headers, body = @r.for_rack
198
+
199
+ expected = JSON.generate(response_hash)
200
+ expect(status).to eq(200) # From the first error we stored, not the second
201
+ expect(headers).to eq({'Content-Length' => expected.length.to_s})
202
+ expect(body.body).to eq([expected])
203
+ end
204
+
205
+ it 'should return non-error condition Rack data correctly with an Array body' do
206
+ response_array = [ { this: 'should not be ignored' }, { neither: 'should this' } ]
207
+ @r.body = response_array
208
+
209
+ status, headers, body = @r.for_rack
210
+
211
+ expected = JSON.generate({'_data' => response_array})
212
+ expect(status).to eq(200) # From the first error we stored, not the second
213
+ expect(headers).to eq({'Content-Length' => expected.length.to_s})
214
+ expect(body.body).to eq([expected])
215
+ end
216
+
217
+ it 'should allow pre-encoded strings in the body' do
218
+ @r.body = 'Hello World!'
219
+
220
+ status, headers, body = @r.for_rack
221
+
222
+ expect(status).to eq(200)
223
+ expect(body.body).to eq(['Hello World!'])
224
+ end
225
+
226
+ it 'should raise an exception when the body is in an unsupported format' do
227
+ @r.body = :foo
228
+
229
+ expect {
230
+ status, headers, body = @r.for_rack
231
+ }.to raise_error(RuntimeError, "Hoodoo::Services::Response\#for_rack given unrecognised body data class 'Symbol'")
232
+ end
233
+ end
234
+
235
+ context "#not_found" do
236
+
237
+ let(:ident) { 'an_ident' }
238
+ before { @r.not_found(ident) }
239
+
240
+ it 'sets the generic.not_found code' do
241
+ expect(@r.errors.errors.first['code']).to eq('generic.not_found')
242
+ end
243
+ it 'sets the the reference to be the ident passed in' do
244
+ expect(@r.errors.errors.first['reference']).to eq(ident)
245
+ end
246
+ it 'sets halt processing to true' do
247
+ expect(@r.halt_processing?).to eq(true)
248
+ end
249
+ end
250
+ end