stormpath-sdk 0.4.0 → 1.0.0.beta
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.
- data/.gitignore +6 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +27 -0
- data/CHANGES.md +21 -1
- data/Gemfile +1 -2
- data/README.md +457 -11
- data/Rakefile +15 -1
- data/lib/stormpath-sdk.rb +52 -33
- data/lib/stormpath-sdk/{resource/group_list.rb → api_key.rb} +5 -9
- data/lib/stormpath-sdk/auth/authentication_result.rb +3 -13
- data/lib/stormpath-sdk/auth/basic_authenticator.rb +5 -11
- data/lib/stormpath-sdk/auth/basic_login_attempt.rb +6 -8
- data/lib/stormpath-sdk/auth/username_password_request.rb +2 -5
- data/lib/stormpath-sdk/cache/cache.rb +54 -0
- data/lib/stormpath-sdk/cache/cache_entry.rb +33 -0
- data/lib/stormpath-sdk/cache/cache_manager.rb +22 -0
- data/lib/stormpath-sdk/cache/cache_stats.rb +35 -0
- data/lib/stormpath-sdk/cache/memory_store.rb +29 -0
- data/lib/stormpath-sdk/cache/redis_store.rb +32 -0
- data/lib/stormpath-sdk/client.rb +111 -0
- data/lib/stormpath-sdk/data_store.rb +241 -0
- data/lib/stormpath-sdk/{client/api_key.rb → error.rb} +16 -10
- data/lib/stormpath-sdk/{util → ext}/hash.rb +1 -2
- data/lib/stormpath-sdk/http/authc/sauthc1_signer.rb +8 -4
- data/lib/stormpath-sdk/http/http_client_request_executor.rb +8 -7
- data/lib/stormpath-sdk/http/request.rb +4 -8
- data/lib/stormpath-sdk/{util/request_utils.rb → http/utils.rb} +17 -38
- data/lib/stormpath-sdk/resource/account.rb +12 -108
- data/lib/stormpath-sdk/resource/application.rb +35 -171
- data/lib/stormpath-sdk/resource/associations.rb +97 -0
- data/lib/stormpath-sdk/resource/base.rb +256 -0
- data/lib/stormpath-sdk/resource/collection.rb +94 -0
- data/lib/stormpath-sdk/resource/directory.rb +11 -68
- data/lib/stormpath-sdk/resource/email_verification_token.rb +3 -9
- data/lib/stormpath-sdk/resource/error.rb +4 -38
- data/lib/stormpath-sdk/resource/expansion.rb +28 -0
- data/lib/stormpath-sdk/resource/group.rb +8 -66
- data/lib/stormpath-sdk/resource/group_membership.rb +4 -55
- data/lib/stormpath-sdk/resource/{application_list.rb → instance.rb} +7 -13
- data/lib/stormpath-sdk/resource/password_reset_token.rb +5 -23
- data/lib/stormpath-sdk/resource/status.rb +22 -28
- data/lib/stormpath-sdk/resource/tenant.rb +5 -52
- data/lib/stormpath-sdk/resource/utils.rb +43 -13
- data/lib/stormpath-sdk/util/assert.rb +5 -15
- data/lib/stormpath-sdk/version.rb +3 -3
- data/spec/api_key_spec.rb +19 -0
- data/spec/auth/basic_authenticator_spec.rb +25 -0
- data/spec/auth/sauthc1_signer_spec.rb +42 -0
- data/spec/cache/cache_entry_spec.rb +157 -0
- data/spec/cache/cache_spec.rb +89 -0
- data/spec/cache/cache_stats_spec.rb +106 -0
- data/spec/client_spec.rb +538 -0
- data/spec/data_store_spec.rb +130 -0
- data/spec/resource/account_spec.rb +74 -0
- data/spec/resource/application_spec.rb +148 -0
- data/spec/resource/base_spec.rb +114 -0
- data/spec/resource/collection_spec.rb +169 -0
- data/spec/resource/directory_spec.rb +30 -0
- data/spec/resource/expansion_spec.rb +100 -0
- data/spec/resource/group_spec.rb +49 -0
- data/spec/spec_helper.rb +135 -0
- data/spec/support/resource_factory.rb +48 -0
- data/spec/support/resource_matchers.rb +27 -0
- data/spec/support/test_cache_stores.rb +9 -0
- data/spec/support/test_request_executor.rb +11 -0
- data/stormpath-sdk.gemspec +14 -4
- data/support/api.rb +55 -0
- metadata +214 -44
- data/lib/stormpath-sdk/client/client.rb +0 -38
- data/lib/stormpath-sdk/client/client_application.rb +0 -38
- data/lib/stormpath-sdk/client/client_application_builder.rb +0 -351
- data/lib/stormpath-sdk/client/client_builder.rb +0 -305
- data/lib/stormpath-sdk/ds/data_store.rb +0 -210
- data/lib/stormpath-sdk/ds/resource_factory.rb +0 -37
- data/lib/stormpath-sdk/resource/account_list.rb +0 -32
- data/lib/stormpath-sdk/resource/collection_resource.rb +0 -91
- data/lib/stormpath-sdk/resource/directory_list.rb +0 -30
- data/lib/stormpath-sdk/resource/group_membership_list.rb +0 -32
- data/lib/stormpath-sdk/resource/instance_resource.rb +0 -28
- data/lib/stormpath-sdk/resource/resource.rb +0 -327
- data/lib/stormpath-sdk/resource/resource_error.rb +0 -47
- data/test/client/client.yml +0 -16
- data/test/client/client_application_builder_spec.rb +0 -114
- data/test/client/client_builder_spec.rb +0 -176
- data/test/client/read_spec.rb +0 -254
- data/test/client/write_spec.rb +0 -420
- data/test/resource/resource_spec.rb +0 -41
- 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
|