stormpath-sdk 0.4.0 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.gitignore +6 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +27 -0
  5. data/CHANGES.md +21 -1
  6. data/Gemfile +1 -2
  7. data/README.md +457 -11
  8. data/Rakefile +15 -1
  9. data/lib/stormpath-sdk.rb +52 -33
  10. data/lib/stormpath-sdk/{resource/group_list.rb → api_key.rb} +5 -9
  11. data/lib/stormpath-sdk/auth/authentication_result.rb +3 -13
  12. data/lib/stormpath-sdk/auth/basic_authenticator.rb +5 -11
  13. data/lib/stormpath-sdk/auth/basic_login_attempt.rb +6 -8
  14. data/lib/stormpath-sdk/auth/username_password_request.rb +2 -5
  15. data/lib/stormpath-sdk/cache/cache.rb +54 -0
  16. data/lib/stormpath-sdk/cache/cache_entry.rb +33 -0
  17. data/lib/stormpath-sdk/cache/cache_manager.rb +22 -0
  18. data/lib/stormpath-sdk/cache/cache_stats.rb +35 -0
  19. data/lib/stormpath-sdk/cache/memory_store.rb +29 -0
  20. data/lib/stormpath-sdk/cache/redis_store.rb +32 -0
  21. data/lib/stormpath-sdk/client.rb +111 -0
  22. data/lib/stormpath-sdk/data_store.rb +241 -0
  23. data/lib/stormpath-sdk/{client/api_key.rb → error.rb} +16 -10
  24. data/lib/stormpath-sdk/{util → ext}/hash.rb +1 -2
  25. data/lib/stormpath-sdk/http/authc/sauthc1_signer.rb +8 -4
  26. data/lib/stormpath-sdk/http/http_client_request_executor.rb +8 -7
  27. data/lib/stormpath-sdk/http/request.rb +4 -8
  28. data/lib/stormpath-sdk/{util/request_utils.rb → http/utils.rb} +17 -38
  29. data/lib/stormpath-sdk/resource/account.rb +12 -108
  30. data/lib/stormpath-sdk/resource/application.rb +35 -171
  31. data/lib/stormpath-sdk/resource/associations.rb +97 -0
  32. data/lib/stormpath-sdk/resource/base.rb +256 -0
  33. data/lib/stormpath-sdk/resource/collection.rb +94 -0
  34. data/lib/stormpath-sdk/resource/directory.rb +11 -68
  35. data/lib/stormpath-sdk/resource/email_verification_token.rb +3 -9
  36. data/lib/stormpath-sdk/resource/error.rb +4 -38
  37. data/lib/stormpath-sdk/resource/expansion.rb +28 -0
  38. data/lib/stormpath-sdk/resource/group.rb +8 -66
  39. data/lib/stormpath-sdk/resource/group_membership.rb +4 -55
  40. data/lib/stormpath-sdk/resource/{application_list.rb → instance.rb} +7 -13
  41. data/lib/stormpath-sdk/resource/password_reset_token.rb +5 -23
  42. data/lib/stormpath-sdk/resource/status.rb +22 -28
  43. data/lib/stormpath-sdk/resource/tenant.rb +5 -52
  44. data/lib/stormpath-sdk/resource/utils.rb +43 -13
  45. data/lib/stormpath-sdk/util/assert.rb +5 -15
  46. data/lib/stormpath-sdk/version.rb +3 -3
  47. data/spec/api_key_spec.rb +19 -0
  48. data/spec/auth/basic_authenticator_spec.rb +25 -0
  49. data/spec/auth/sauthc1_signer_spec.rb +42 -0
  50. data/spec/cache/cache_entry_spec.rb +157 -0
  51. data/spec/cache/cache_spec.rb +89 -0
  52. data/spec/cache/cache_stats_spec.rb +106 -0
  53. data/spec/client_spec.rb +538 -0
  54. data/spec/data_store_spec.rb +130 -0
  55. data/spec/resource/account_spec.rb +74 -0
  56. data/spec/resource/application_spec.rb +148 -0
  57. data/spec/resource/base_spec.rb +114 -0
  58. data/spec/resource/collection_spec.rb +169 -0
  59. data/spec/resource/directory_spec.rb +30 -0
  60. data/spec/resource/expansion_spec.rb +100 -0
  61. data/spec/resource/group_spec.rb +49 -0
  62. data/spec/spec_helper.rb +135 -0
  63. data/spec/support/resource_factory.rb +48 -0
  64. data/spec/support/resource_matchers.rb +27 -0
  65. data/spec/support/test_cache_stores.rb +9 -0
  66. data/spec/support/test_request_executor.rb +11 -0
  67. data/stormpath-sdk.gemspec +14 -4
  68. data/support/api.rb +55 -0
  69. metadata +214 -44
  70. data/lib/stormpath-sdk/client/client.rb +0 -38
  71. data/lib/stormpath-sdk/client/client_application.rb +0 -38
  72. data/lib/stormpath-sdk/client/client_application_builder.rb +0 -351
  73. data/lib/stormpath-sdk/client/client_builder.rb +0 -305
  74. data/lib/stormpath-sdk/ds/data_store.rb +0 -210
  75. data/lib/stormpath-sdk/ds/resource_factory.rb +0 -37
  76. data/lib/stormpath-sdk/resource/account_list.rb +0 -32
  77. data/lib/stormpath-sdk/resource/collection_resource.rb +0 -91
  78. data/lib/stormpath-sdk/resource/directory_list.rb +0 -30
  79. data/lib/stormpath-sdk/resource/group_membership_list.rb +0 -32
  80. data/lib/stormpath-sdk/resource/instance_resource.rb +0 -28
  81. data/lib/stormpath-sdk/resource/resource.rb +0 -327
  82. data/lib/stormpath-sdk/resource/resource_error.rb +0 -47
  83. data/test/client/client.yml +0 -16
  84. data/test/client/client_application_builder_spec.rb +0 -114
  85. data/test/client/client_builder_spec.rb +0 -176
  86. data/test/client/read_spec.rb +0 -254
  87. data/test/client/write_spec.rb +0 -420
  88. data/test/resource/resource_spec.rb +0 -41
  89. data/test/resource/test_resource.rb +0 -28
@@ -1,38 +0,0 @@
1
- #
2
- # Copyright 2012 Stormpath, Inc.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Stormpath
17
-
18
- module Client
19
-
20
- class Client
21
-
22
- attr_reader :data_store
23
-
24
- def initialize(api_key, *base_url)
25
- request_executor = Stormpath::Http::HttpClientRequestExecutor.new(api_key)
26
- @data_store = Stormpath::DataStore::DataStore.new(request_executor, *base_url)
27
- end
28
-
29
-
30
- def current_tenant
31
- @data_store.get_resource("/tenants/current", Stormpath::Resource::Tenant)
32
- end
33
- end
34
- end
35
-
36
-
37
- end
38
-
@@ -1,38 +0,0 @@
1
- #
2
- # Copyright 2012 Stormpath, Inc.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Stormpath
17
-
18
- module Client
19
-
20
- # A ClientApplication is a simple wrapper around a {@link Stormpath::Client::Client} and
21
- # {@link Stormpath::Resource::Application} instance, returned from
22
- # the {@code ClientApplicationBuilder}.{@link Stormpath::Client::ClientApplicationBuilder#build_application}
23
- # method.
24
- # @since 0.3.0
25
- class ClientApplication
26
-
27
- attr_reader :client, :application
28
-
29
- def initialize client, application
30
- @client = client
31
- @application = application
32
- end
33
-
34
- end
35
-
36
- end
37
-
38
- end
@@ -1,351 +0,0 @@
1
- #
2
- # Copyright 2012 Stormpath, Inc.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Stormpath
17
-
18
- module Client
19
-
20
- ##
21
- # A <a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder design pattern</a> implementation similar to
22
- # the {@link Stormpath::Client::ClientBuilder}, but focused on single-application interaction with Stormpath.
23
- # <h2>Description</h2>
24
- # The {@code ClientBuilder} produces a {@link Stormpath::Client::Client} instance useful for interacting with any aspect
25
- # of an entire Stormpath Tenant's data space. However, a software application may only be interested in its own
26
- # functionality and not the entire Stormpath Tenant data space.
27
- # <p/>
28
- # The {@code ClientApplicationBuilder} provides a means to more easily acquiring a single
29
- # {@link Stormpath::Resource::Application} instance. From this {@code Application} instance, everything a particular
30
- # Application needs to perform can be based off of this instance and the wider-scoped concerns of an entire Tenant can be ignored.
31
- # <h2>Default Usage</h2>
32
- # <pre>
33
- # # this can be a file disk or url location as well:
34
- # location = "/home/jsmith/.stormpath/apiKey.yml"
35
- #
36
- # app_href = "https://api.stormpath.com/v1/applications/YOUR_APP_UID_HERE"
37
- #
38
- # application = new ClientApplicationBuilder.new.
39
- # set_api_key_file_location(location).
40
- # <b>set_application_href(app_href)</b>.
41
- # build.
42
- # application
43
- # </pre>
44
- # <p/>
45
- # After acquiring the {@code Application} instance, you can interact with it to login accounts, reset passwords,
46
- # etc.
47
- # <h2>Service Provider Usage with only an Application URL</h2>
48
- # Some hosting service providers (e.g. like <a href="http://www.heroku.com">Heroku</a>) do not allow easy access to
49
- # a configuration file and therefore it might be difficult to reference an API Key File. If you cannot reference an
50
- # API Key File via the {@code YAML file} or {@code YAML object} or {@code url}
51
- # {@link ClientBuilder#set_api_key_file_location(String) resource locations}, the Application HREF URL must contain the
52
- # API Key embedded as the <em><a href="http://en.wikipedia.org/wiki/URI_scheme">user info</a></em> portion of the
53
- # URL. For example:
54
- # <p/>
55
- # <pre>
56
- # https://<b>apiKeyId:apiKeySecret@</b>api.stormpath.com/v1/applications/YOUR_APP_UID_HERE
57
- # </pre>
58
- # <p/>
59
- # Notice this is just a normal Application HREF url with the <b>apiKeyId:apiKeySecret@</b> part added in.
60
- # <p/>
61
- # Example usage:
62
- # <pre>
63
- # appHref = "https://<b>apiKeyId:apiKeySecret@</b>api.stormpath.com/v1/applications/YOUR_APP_UID_HERE";
64
- #
65
- # application = new ClientApplicationBuilder.new.
66
- # <b>set_application_href(appHref)</b>.
67
- # build.
68
- # application
69
- # </pre>
70
- # <p/>
71
- # <b>WARNING: ONLY use the embedded API Key technique if you do not have access to {@code YAML file} or
72
- # {@code YAML object} or {@code url} {@link ClientApplicationBuilder#set_api_key_file_location(String) resource locations}</b>.
73
- # File based API Key storage is a more secure technique than embedding the key in the URL itself. Also, again,
74
- # NEVER share your API Key Secret with <em>anyone</em> (not even co-workers).
75
- # Stormpath staff will never ask for your API Key Secret.
76
- #
77
- # @see #set_api_key_file_location(String)
78
- # @see #set_application_href(String)
79
- # @since 0.3.0
80
- #
81
- class ClientApplicationBuilder
82
-
83
- include Stormpath::Client
84
- include Stormpath::Util::Assert
85
-
86
- DOUBLE_SLASH = "//"
87
-
88
- def initialize client_builder = ClientBuilder.new
89
-
90
- assert_kind_of ClientBuilder, client_builder, 'client_builder must be kind of Stormpath::Client::ClientBuilder'
91
- @client_builder = client_builder
92
-
93
- end
94
-
95
- # Allows usage of a YAML loadable object (IO object or the result of invoking Object.to_yaml)
96
- # instead of loading a YAML file via {@link #set_api_key_file_location apiKeyFileLocation} configuration.
97
- # <p/>
98
- # The YAML contents and property name overrides function the same as described in the
99
- # {@link #set_api_key_file_location setApiKeyFileLocation} RDoc.
100
- #
101
- # @param properties the YAML object to use to load the API Key ID and Secret.
102
- # @return this ClientApplicationBuilder instance for method chaining.
103
- def set_api_key_properties properties
104
-
105
- @client_builder.set_api_key_properties properties
106
- self
107
-
108
- end
109
-
110
- # Creates an API Key YAML object based on the specified File instead of loading a YAML
111
- # file via {@link #set_api_key_file_location apiKeyFileLocation} configuration. This file argument
112
- # needs to be an IO instance.
113
- # <p/>
114
- # The constructed YAML contents and property name overrides function the same as described in the
115
- # {@link #set_api_key_file_location setApiKeyFileLocation} RDoc.
116
- # @param file the file to use to construct a YAML object.
117
- # @return this ClientApplicationBuilder instance for method chaining.
118
- def set_api_key_file file
119
-
120
- @client_builder.set_api_key_file file
121
- self
122
-
123
- end
124
-
125
- # Sets the location of the YAML file to load containing the API Key (Id and secret) used by the
126
- # Client to communicate with the Stormpath REST API.
127
- # <p/>
128
- # You may load files from the filesystem, or URLs just specifying the file location.
129
- # <h3>File Contents</h3>
130
- # <p/>
131
- # When the file is loaded, the following name/value pairs are expected to be present by default:
132
- # <table>
133
- # <tr>
134
- # <th>Key</th>
135
- # <th>Value</th>
136
- # </tr>
137
- # <tr>
138
- # <td>apiKey.id</td>
139
- # <td>An individual account's API Key ID</td>
140
- # </tr>
141
- # <tr>
142
- # <td>apiKey.secret</td>
143
- # <td>The API Key Secret (password) that verifies the paired API Key ID.</td>
144
- # </tr>
145
- # </table>
146
- # <p/>
147
- # Assuming you were using these default property names, your {@code ClientApplicationBuilder} usage might look like the
148
- # following:
149
- # <pre>
150
- # location = "/home/jsmith/.stormpath/apiKey.yml";
151
- #
152
- # application_href = 'https://<b>apiKeyId:apiKeySecret@</b>api.stormpath.com/v1/applications/YOUR_APP_UID_HERE'
153
- #
154
- # application = ClientApplicationBuilder.new.
155
- # set_application_href(application_href).
156
- # set_api_key_file_location(location).
157
- # build.
158
- # application
159
- # </pre>
160
- # <h3>Custom Property Names</h3>
161
- # If you want to control the property names used in the file, you may configure them via
162
- # {@link #set_api_key_id_property_name(String) set_api_key_id_property_name} and
163
- # {@link #set_api_key_secret_property_name(String) set_api_key_secret_property_name}.
164
- # <p/>
165
- # For example, if you had a {@code /home/jsmith/.stormpath/apiKey.yml} file with the following
166
- # name/value pairs:
167
- # <pre>
168
- # myStormpathApiKeyId = 'foo'
169
- # myStormpathApiKeySecret = 'mySuperSecretValue'
170
- # </pre>
171
- # Your {@code ClientApplicationBuilder} usage would look like the following:
172
- # <pre>
173
- # location = "/home/jsmith/.stormpath/apiKey.yml";
174
- #
175
- # application = ClientApplicationBuilder.new.
176
- # set_api_key_file_location(location).
177
- # set_api_key_id_property_name("myStormpathApiKeyId").
178
- # set_api_key_secret_property_name("myStormpathApiKeySecret").
179
- # set_application_href(application_href).
180
- # build.
181
- # application
182
- # </pre>
183
- #
184
- # @param location the file or url location of the API Key {@code .yml} file to load when
185
- # constructing the API Key to use for communicating with the Stormpath REST API.
186
- #
187
- # @return this ClientApplicationBuilder instance for method chaining.
188
- #/
189
- def set_api_key_file_location location
190
-
191
- @client_builder.set_api_key_file_location location
192
- self
193
-
194
- end
195
-
196
- # Sets the name used to query for the API Key ID from a YAML instance. That is:
197
- # <pre>
198
- # apiKeyId = yml.access(<b>api_key_id_property_name</b>)
199
- # </pre>
200
- #
201
- # The Hash#access method searches through the provided path and returns the found value.
202
- #
203
- # The <b>api_key_id_property_name</b> key can be as deep as needed, as long as it comes
204
- # in the exact path order.
205
- # Example: Having the file 'apiKey.yml' with the following content:
206
- #
207
- # stormpath:
208
- # apiKey:
209
- # id: myStormpathApiKeyId
210
- #
211
- # The method should be called as follows:
212
- #
213
- # ClientApplicationBuilder#set_api_key_id_property_name('stormpath', 'apiKey', 'id')
214
- #
215
- # @param api_key_id_property_name the name used to query for the API Key ID from a YAML instance.
216
- # @return this ClientApplicationBuilder instance for method chaining.
217
- def set_api_key_id_property_name *api_key_id_property_name
218
-
219
- @client_builder.set_api_key_id_property_name *api_key_id_property_name
220
- self
221
-
222
- end
223
-
224
- # Sets the name used to query for the API Key Secret from a YAML instance. That is:
225
- # <pre>
226
- # apiKeyId = yml.access(<b>api_key_secret_property_name</b>)
227
- # </pre>
228
- #
229
- # The Hash#access method searches through the provided path and returns the found value.
230
- #
231
- # The <b>api_key_secret_property_name</b> key can be as deep as needed, as long as it comes
232
- # in the exact path order.
233
- # Example: Having the file 'apiKey.yml' with the following content:
234
- #
235
- # stormpath:
236
- # apiKey:
237
- # secret: myStormpathApiKeyId
238
- #
239
- # The method should be called as follows:
240
- #
241
- # ClientApplicationBuilder#set_api_key_id_property_name('stormpath', 'apiKey', 'secret')
242
- #
243
- # @param api_key_secret_property_name the name used to query for the API Key Secret from a YAML instance.
244
- # @return this ClientApplicationBuilder instance for method chaining.
245
- def set_api_key_secret_property_name *api_key_secret_property_name
246
-
247
- @client_builder.set_api_key_secret_property_name *api_key_secret_property_name
248
- self
249
-
250
- end
251
-
252
- ##
253
- # Sets the fully qualified Stormpath Application HREF (a URL) to use to acquire the Application instance when
254
- # {@link #build_application} is called. See the Class-level RDoc for usage scenarios.
255
- #
256
- # @param applicationHref the fully qualified Stormpath Application HREF (a URL) to use to acquire the
257
- # Application instance when {@link #build_application} is called.
258
- # @return this ClientApplicationBuilder instance for method chaining.
259
- def set_application_href application_href
260
-
261
- @application_href = application_href
262
- self
263
-
264
- end
265
-
266
- # Builds a Client and Application wrapper instance based on the configured
267
- # {@link #set_application_href}. See the Class-level RDoc for usage scenarios.
268
- #
269
- # @return a Client and Application wrapper instance based on the configured {@link #set_application_href}.
270
- def build
271
-
272
- href = !@application_href.nil? ? @application_href.strip : nil
273
-
274
- assert_false (href.nil? or href.empty?),
275
- "'application_href' property must be specified when using this builder implementation."
276
-
277
-
278
- cleaned_href = href
279
-
280
- at_sigh_index = href.index '@'
281
-
282
- if !at_sigh_index.nil?
283
-
284
- parts = get_href_with_user_info href, at_sigh_index
285
-
286
- cleaned_href = parts[0] + parts[2]
287
-
288
- parts = parts[1].split ':', 2
289
-
290
- api_key_properties = create_api_key_properties parts
291
-
292
- set_api_key_properties api_key_properties
293
-
294
- end #otherwise an apiKey File/YAML/etc for the API Key is required
295
-
296
- client = build_client
297
-
298
- application = client.data_store.get_resource cleaned_href, Stormpath::Resource::Application
299
-
300
- ClientApplication.new client, application
301
-
302
- end
303
-
304
- protected
305
-
306
- def build_client
307
- @client_builder.build
308
- end
309
-
310
- def get_href_with_user_info href, at_sign_index
311
-
312
- assert_kind_of String, href, 'href must be kind of String'
313
- assert_kind_of Fixnum, at_sign_index, 'at_sign_index must be kind of Fixnum'
314
-
315
- double_slash_index = href.index DOUBLE_SLASH
316
-
317
- assert_not_nil double_slash_index, 'Invalid application href URL'
318
-
319
- parts = Array.new 3
320
-
321
- parts[0] = href[0..double_slash_index + 1] #up to and including the double slash
322
- parts[1] = href[double_slash_index + DOUBLE_SLASH.length..at_sign_index - 1] #raw user info
323
- parts[2] = href[at_sign_index + 1..href.length - 1] #after the @ character
324
-
325
- parts
326
-
327
- end
328
-
329
- def create_api_key_properties pair
330
-
331
- assert_kind_of Array, pair, 'pair must be kind of Array'
332
-
333
- assert_true (pair.length == 2), 'application_href userInfo segment must consist' +
334
- ' of the following format: apiKeyId:apiKeySecret'
335
-
336
- properties = Hash.new
337
- properties.store 'apiKey.id', url_decode(pair[0])
338
- properties.store 'apiKey.secret', url_decode(pair[1])
339
-
340
- properties.to_yaml
341
-
342
- end
343
-
344
- def url_decode url
345
- URI.decode url
346
- end
347
- end
348
-
349
- end
350
-
351
- end
@@ -1,305 +0,0 @@
1
- #
2
- # Copyright 2012 Stormpath, Inc.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Stormpath
17
-
18
- module Client
19
-
20
- # A <a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder design pattern</a> implementation used to
21
- # construct {@link Client} instances.
22
- # <p/>
23
- # The {@code ClientBuilder} is especially useful for constructing Client instances with Stormpath API Key
24
- # information loaded from an external {@code .yml} file (or YAML instance) to ensure the API Key secret
25
- # (password) does not reside in plaintext in code.
26
- # <p/>
27
- # Example usage:
28
- # <pre>
29
- # location = "/home/jsmith/.stormpath/apiKey.yml";
30
- #
31
- # client = ClientBuilder.new.set_api_key_file_location(location).build
32
- # </pre>
33
- # <p/>
34
- # You may load files from the filesystem or URLs by specifying the file location.
35
- # See {@link #set_api_key_file_location(location)} for more information.
36
- #
37
- # @see #set_api_key_file_location(location)
38
- class ClientBuilder
39
-
40
- include Stormpath::Client
41
- include Stormpath::Util::Assert
42
-
43
- def initialize
44
- @api_key_id_property_name = "apiKey.id"
45
- @api_key_secret_property_name = "apiKey.secret"
46
- end
47
-
48
- # Allows usage of a YAML loadable object (IO object or the result of invoking Object.to_yaml)
49
- # instead of loading a YAML file via {@link #set_api_key_file_location apiKeyFileLocation} configuration.
50
- # <p/>
51
- # The YAML contents and property name overrides function the same as described in the
52
- # {@link #set_api_key_file_location setApiKeyFileLocation} RDoc.
53
- #
54
- # @param properties the YAML object to use to load the API Key ID and Secret.
55
- # @return the ClientBuilder instance for method chaining.
56
- def set_api_key_properties properties
57
-
58
- @api_key_properties = properties
59
- self
60
-
61
- end
62
-
63
- # Creates an API Key YAML object based on the specified File instead of loading a YAML
64
- # file via {@link #set_api_key_file_location apiKeyFileLocation} configuration. This file argument
65
- # needs to be an IO instance.
66
- # <p/>
67
- # The constructed YAML contents and property name overrides function the same as described in the
68
- # {@link #set_api_key_file_location setApiKeyFileLocation} RDoc.
69
- # @param file the file to use to construct a YAML object.
70
- # @return the ClientBuilder instance for method chaining.
71
- def set_api_key_file file
72
- assert_kind_of IO, file, 'file must be kind of IO'
73
- @api_key_file = file
74
- self
75
- end
76
-
77
-
78
- # Sets the location of the YAML file to load containing the API Key (Id and secret) used by the
79
- # Client to communicate with the Stormpath REST API.
80
- # <p/>
81
- # You may load files from the filesystem, or URLs just specifying the file location.
82
- # <h3>File Contents</h3>
83
- # <p/>
84
- # When the file is loaded, the following name/value pairs are expected to be present by default:
85
- # <table>
86
- # <tr>
87
- # <th>Key</th>
88
- # <th>Value</th>
89
- # </tr>
90
- # <tr>
91
- # <td>apiKey.id</td>
92
- # <td>An individual account's API Key ID</td>
93
- # </tr>
94
- # <tr>
95
- # <td>apiKey.secret</td>
96
- # <td>The API Key Secret (password) that verifies the paired API Key ID.</td>
97
- # </tr>
98
- # </table>
99
- # <p/>
100
- # Assuming you were using these default property names, your {@code ClientBuilder} usage might look like the
101
- # following:
102
- # <pre>
103
- # location = "/home/jsmith/.stormpath/apiKey.yml";
104
- #
105
- # client = ClientBuilder.new.set_api_key_file_location(location).build
106
- # </pre>
107
- # <h3>Custom Property Names</h3>
108
- # If you want to control the property names used in the file, you may configure them via
109
- # {@link #set_api_key_id_property_name(String) set_api_key_id_property_name} and
110
- # {@link #set_api_key_secret_property_name(String) set_api_key_secret_property_name}.
111
- # <p/>
112
- # For example, if you had a {@code /home/jsmith/.stormpath/apiKey.yml} file with the following
113
- # name/value pairs:
114
- # <pre>
115
- # myStormpathApiKeyId = 'foo'
116
- # myStormpathApiKeySecret = 'mySuperSecretValue'
117
- # </pre>
118
- # Your {@code ClientBuilder} usage would look like the following:
119
- # <pre>
120
- # location = "/home/jsmith/.stormpath/apiKey.yml";
121
- #
122
- # client =
123
- # ClientBuilder.new.
124
- # set_api_key_file_location(location).
125
- # set_api_key_id_property_name("myStormpathApiKeyId").
126
- # set_api_key_secret_property_name("myStormpathApiKeySecret").
127
- # build
128
- # </pre>
129
- #
130
- # @param location the file or url location of the API Key {@code .yml} file to load when
131
- # constructing the API Key to use for communicating with the Stormpath REST API.
132
- #
133
- # @return the ClientBuilder instance for method chaining.
134
- #/
135
- def set_api_key_file_location location
136
-
137
- assert_kind_of String, location, 'location must be kind of String'
138
- @api_key_file_location = location
139
- self
140
-
141
- end
142
-
143
-
144
- # Sets the name used to query for the API Key ID from a YAML instance. That is:
145
- # <pre>
146
- # apiKeyId = yml.access(<b>api_key_id_property_name</b>)
147
- # </pre>
148
- #
149
- # The Hash#access method searches through the provided path and returns the found value.
150
- #
151
- # The <b>api_key_id_property_name</b> key can be as deep as needed, as long as it comes
152
- # in the exact path order.
153
- # Example: Having the file 'apiKey.yml' with the following content:
154
- #
155
- # stormpath:
156
- # apiKey:
157
- # id: myStormpathApiKeyId
158
- #
159
- # The method should be called as follows:
160
- #
161
- # ClientBuilder#set_api_key_id_property_name('stormpath', 'apiKey', 'id')
162
- #
163
- # @param api_key_id_property_name the name used to query for the API Key ID from a YAML instance.
164
- # @return the ClientBuilder instance for method chaining.
165
- def set_api_key_id_property_name *api_key_id_property_name
166
-
167
- @api_key_id_property_name = *api_key_id_property_name
168
- self
169
-
170
- end
171
-
172
-
173
- # Sets the name used to query for the API Key Secret from a YAML instance. That is:
174
- # <pre>
175
- # apiKeyId = yml.access(<b>api_key_secret_property_name</b>)
176
- # </pre>
177
- #
178
- # The Hash#access method searches through the provided path and returns the found value.
179
- #
180
- # The <b>api_key_secret_property_name</b> key can be as deep as needed, as long as it comes
181
- # in the exact path order.
182
- # Example: Having the file 'apiKey.yml' with the following content:
183
- #
184
- # stormpath:
185
- # apiKey:
186
- # secret: myStormpathApiKeyId
187
- #
188
- # The method should be called as follows:
189
- #
190
- # ClientBuilder#set_api_key_id_property_name('stormpath', 'apiKey', 'secret')
191
- #
192
- # @param api_key_secret_property_name the name used to query for the API Key Secret from a YAML instance.
193
- # @return the ClientBuilder instance for method chaining.
194
- def set_api_key_secret_property_name *api_key_secret_property_name
195
-
196
- @api_key_secret_property_name = *api_key_secret_property_name
197
- self
198
-
199
- end
200
-
201
- # Constructs a new {@link Client} instance based on the ClientBuilder's current configuration state.
202
- #
203
- # @return a new {@link Client} instance based on the ClientBuilder's current configuration state.
204
- #
205
- def build
206
-
207
- if @api_key_properties.nil? or (@api_key_properties.respond_to? 'empty?' and @api_key_properties.empty?)
208
-
209
-
210
- #need to load the properties file
211
-
212
- file = get_available_file
213
-
214
- assert_not_nil file, "No API Key file could be found or loaded from a file location. Please " +
215
- "configure the 'apiKeyFileLocation' property or alternatively configure a " +
216
- "YAML loadable instance."
217
-
218
- yaml_obj = YAML::load(file)
219
-
220
- else
221
-
222
- yaml_obj = YAML::load(@api_key_properties)
223
-
224
- end
225
-
226
- api_key_id = get_required_property_value yaml_obj, 'api_key_id', @api_key_id_property_name
227
-
228
- api_key_secret = get_required_property_value yaml_obj, 'api_key_secret', @api_key_secret_property_name
229
-
230
- assert_not_nil api_key_id, 'api_key_id must not be nil when acquiring it from the YAML object'
231
- assert_not_nil api_key_secret, 'api_key_secret must not be nil when acquiring it from the YAML object'
232
-
233
- api_key = ApiKey.new api_key_id, api_key_secret
234
-
235
- Client.new api_key, @base_url
236
-
237
- end
238
-
239
- def set_base_url base_url
240
-
241
- @base_url = base_url
242
- self
243
-
244
- end
245
-
246
- private
247
-
248
-
249
- def get_property_value yml, prop_name, separator
250
-
251
- value = yml.access(prop_name, separator)
252
-
253
- if !value.nil?
254
-
255
- if value.kind_of? String
256
-
257
- value = value.strip
258
-
259
- end
260
-
261
- if value.empty?
262
- value = nil
263
- end
264
-
265
- end
266
-
267
- value
268
-
269
- end
270
-
271
- def get_required_property_value yml, masterName, *prop_name
272
-
273
-
274
- prop_name_value = prop_name[0]
275
-
276
- separator = '--YAMLKeysSeparator--'
277
- value = get_property_value(yml, prop_name_value.respond_to?('join') ?
278
- prop_name[0].join(separator) :
279
- prop_name_value,
280
- separator)
281
-
282
- assert_not_nil value, "There is no '" + prop_name.join(':') + "' property in the " +
283
- "configured apiKey YAML. You can either specify that property or " +
284
- "configure the #{masterName}_property_name value on the ClientBuilder to specify a " +
285
- "custom property name."
286
-
287
- value
288
-
289
- end
290
-
291
- def get_available_file
292
-
293
- if @api_key_file
294
- return @api_key_file
295
- end
296
-
297
- open(@api_key_file_location) { |f| f.read }
298
-
299
- end
300
-
301
- end
302
-
303
- end
304
-
305
- end