stormpath-sdk 1.0.0.beta.5 → 1.0.0.beta.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -1
- data/.travis.yml +3 -0
- data/CHANGES.md +10 -0
- data/README.md +2 -2
- data/lib/stormpath-sdk.rb +17 -10
- data/lib/stormpath-sdk/cache/disabled_cache_store.rb +26 -0
- data/lib/stormpath-sdk/client.rb +25 -37
- data/lib/stormpath-sdk/data_store.rb +60 -24
- data/lib/stormpath-sdk/http/authc/sauthc1_signer.rb +58 -95
- data/lib/stormpath-sdk/http/utils.rb +6 -18
- data/lib/stormpath-sdk/resource/associations.rb +16 -16
- data/lib/stormpath-sdk/resource/base.rb +65 -58
- data/lib/stormpath-sdk/resource/collection.rb +41 -21
- data/lib/stormpath-sdk/resource/custom_data.rb +11 -5
- data/lib/stormpath-sdk/resource/custom_data_hash_methods.rb +2 -2
- data/lib/stormpath-sdk/resource/custom_data_storage.rb +1 -1
- data/lib/stormpath-sdk/version.rb +2 -2
- data/spec/client_spec.rb +20 -1
- data/spec/data_store_spec.rb +18 -2
- data/spec/resource/account_spec.rb +1 -1
- data/spec/resource/account_store_mapping_spec.rb +85 -14
- data/spec/resource/collection_spec.rb +201 -1
- data/spec/resource/custom_data_spec.rb +12 -185
- data/spec/resource/directory_spec.rb +2 -4
- data/spec/spec_helper.rb +8 -4
- data/spec/support/custom_data_storage_behavior.rb +391 -0
- data/spec/support/resource_factory.rb +1 -1
- data/support/api.rb +1 -1
- metadata +56 -97
- data/.ruby-version +0 -1
@@ -24,28 +24,16 @@ module Stormpath
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def encode_url(value, path, canonical)
|
27
|
-
URI.escape(value.to_s)
|
28
|
-
if canonical
|
29
|
-
str_map = {'+' => '%20', '*' => '%2A', '%7E' => '~'}
|
27
|
+
return URI.escape(value.to_s) if path
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
# encoded['%7E'] = '~' --> yes, this is reversed (compared to the other two) intentionally
|
38
|
-
|
39
|
-
if path
|
40
|
-
str = '%2F'
|
41
|
-
if encoded.include? str
|
42
|
-
encoded[str] = '/'
|
43
|
-
end
|
44
|
-
end
|
29
|
+
CGI.escape(value.to_s).tap do |encoded|
|
30
|
+
str_map = {'+' => '%20', '%7E' => '~' }
|
31
|
+
str_map.each do |key, str_value|
|
32
|
+
encoded.gsub!(key, str_value) if encoded.include? key
|
45
33
|
end
|
46
34
|
end
|
47
35
|
end
|
48
36
|
|
49
37
|
end
|
50
38
|
end
|
51
|
-
end
|
39
|
+
end
|
@@ -39,9 +39,7 @@ module Stormpath
|
|
39
39
|
|
40
40
|
define_method(name) do
|
41
41
|
href = options[:href] || get_resource_href_property(property_name)
|
42
|
-
collection_href = if options[:delegate]
|
43
|
-
"#{tenant.send(name.to_s).href}"
|
44
|
-
end
|
42
|
+
collection_href = "#{tenant.send(name).href}" if options[:delegate]
|
45
43
|
|
46
44
|
Stormpath::Resource::Collection.new(href, item_class, client,
|
47
45
|
collection_href: collection_href).tap do |collection|
|
@@ -57,7 +55,7 @@ module Stormpath
|
|
57
55
|
end
|
58
56
|
data_store.create href, resource, item_class, options
|
59
57
|
end
|
60
|
-
end
|
58
|
+
end#can.include? :create
|
61
59
|
|
62
60
|
if can.include? :get
|
63
61
|
def get(id_or_href, expansion=nil)
|
@@ -68,15 +66,15 @@ module Stormpath
|
|
68
66
|
end
|
69
67
|
data_store.get_resource item_href, item_class, (expansion ? expansion.to_query : nil)
|
70
68
|
end
|
71
|
-
end
|
72
|
-
end
|
69
|
+
end#can.include? :get
|
70
|
+
end#collection.class_eval do
|
73
71
|
|
74
72
|
collection.class_eval(&block) if block
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
73
|
+
end#Stormpath::Resource::Collection.new
|
74
|
+
end#define_method(name)
|
75
|
+
end#def has_many
|
78
76
|
|
79
|
-
end
|
77
|
+
end#module Class Methods
|
80
78
|
|
81
79
|
included do
|
82
80
|
|
@@ -85,12 +83,14 @@ module Stormpath
|
|
85
83
|
def get_resource_property(key, clazz)
|
86
84
|
value = get_property key
|
87
85
|
|
86
|
+
return nil if value.nil? and clazz != Stormpath::Resource::CustomData
|
87
|
+
|
88
88
|
if value.is_a? Hash
|
89
|
-
|
89
|
+
resource_href = get_href_from_hash value
|
90
90
|
end
|
91
91
|
|
92
92
|
if instance_variable_get("@_#{key.underscore}").nil?
|
93
|
-
if
|
93
|
+
if resource_href
|
94
94
|
instance_variable_set("@_#{key.underscore}", data_store.instantiate(clazz, value))
|
95
95
|
else
|
96
96
|
instance_variable_set("@_#{key.underscore}", clazz.new(value))
|
@@ -109,7 +109,7 @@ module Stormpath
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
112
|
+
end#included do
|
113
|
+
end#Associations
|
114
|
+
end#Resource
|
115
|
+
end#Stormpath
|
@@ -19,7 +19,7 @@ class Stormpath::Resource::Base
|
|
19
19
|
|
20
20
|
HREF_PROP_NAME = "href"
|
21
21
|
DEFAULT_SERVER_HOST = Stormpath::DataStore::DEFAULT_SERVER_HOST
|
22
|
-
attr_reader :client, :properties
|
22
|
+
attr_reader :client, :properties, :dirty_properties
|
23
23
|
|
24
24
|
class << self
|
25
25
|
def prop_reader(*args)
|
@@ -137,8 +137,12 @@ class Stormpath::Resource::Base
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
def get_property name
|
141
|
-
property_name = name.to_s
|
140
|
+
def get_property name, options = {}
|
141
|
+
property_name = name.to_s
|
142
|
+
|
143
|
+
unless options[:ignore_camelcasing] == true
|
144
|
+
property_name = property_name.camelize(:lower)
|
145
|
+
end
|
142
146
|
|
143
147
|
if HREF_PROP_NAME != property_name
|
144
148
|
#not the href/id, must be a property that requires materialization:
|
@@ -165,8 +169,13 @@ class Stormpath::Resource::Base
|
|
165
169
|
read_property property_name
|
166
170
|
end
|
167
171
|
|
168
|
-
def set_property name, value
|
169
|
-
property_name = name.to_s
|
172
|
+
def set_property name, value, options={}
|
173
|
+
property_name = name.to_s
|
174
|
+
|
175
|
+
unless options[:ignore_camelcasing] == true
|
176
|
+
property_name = property_name.camelize(:lower)
|
177
|
+
end
|
178
|
+
|
170
179
|
@write_lock.lock
|
171
180
|
|
172
181
|
begin
|
@@ -186,77 +195,75 @@ class Stormpath::Resource::Base
|
|
186
195
|
end
|
187
196
|
end
|
188
197
|
|
189
|
-
|
198
|
+
private
|
190
199
|
|
191
|
-
|
192
|
-
|
193
|
-
|
200
|
+
def data_store
|
201
|
+
client.data_store
|
202
|
+
end
|
194
203
|
|
195
|
-
|
196
|
-
|
197
|
-
|
204
|
+
def materialized?
|
205
|
+
@materialized
|
206
|
+
end
|
198
207
|
|
199
|
-
|
200
|
-
|
208
|
+
def materialize
|
209
|
+
clazz = self.class
|
201
210
|
|
202
|
-
|
211
|
+
@write_lock.lock
|
203
212
|
|
204
|
-
|
205
|
-
|
206
|
-
|
213
|
+
begin
|
214
|
+
resource = data_store.get_resource href, clazz, @query
|
215
|
+
@properties.replace resource.properties
|
207
216
|
|
208
|
-
|
209
|
-
|
217
|
+
#retain dirty properties:
|
218
|
+
@properties.merge! @dirty_properties
|
210
219
|
|
211
|
-
|
212
|
-
|
213
|
-
|
220
|
+
@materialized = true
|
221
|
+
ensure
|
222
|
+
@write_lock.unlock
|
223
|
+
end
|
214
224
|
end
|
215
|
-
end
|
216
225
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
private
|
226
|
+
def printable_property? property_name
|
227
|
+
!self.class.non_printable_properties.include? property_name
|
228
|
+
end
|
222
229
|
|
223
|
-
|
224
|
-
|
225
|
-
|
230
|
+
def get_href_from_hash(props)
|
231
|
+
if props and props.is_a? Hash
|
232
|
+
props[HREF_PROP_NAME]
|
233
|
+
end
|
226
234
|
end
|
227
|
-
end
|
228
235
|
|
229
|
-
|
230
|
-
|
236
|
+
def read_property name
|
237
|
+
@read_lock.lock
|
231
238
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
239
|
+
begin
|
240
|
+
@properties[name]
|
241
|
+
ensure
|
242
|
+
@read_lock.unlock
|
243
|
+
end
|
236
244
|
end
|
237
|
-
end
|
238
245
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
246
|
+
def sanitize(properties)
|
247
|
+
{}.tap do |sanitized_properties|
|
248
|
+
properties.map do |key, value|
|
249
|
+
property_name = key.to_s.camelize :lower
|
250
|
+
sanitized_properties[property_name] =
|
251
|
+
if (value.kind_of? Hash or value.kind_of? Stormpath::Resource::Base) and property_name != "customData"
|
252
|
+
deep_sanitize value
|
253
|
+
else
|
254
|
+
value
|
255
|
+
end
|
256
|
+
end
|
249
257
|
end
|
250
258
|
end
|
251
|
-
end
|
252
259
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
260
|
+
def deep_sanitize(hash_or_resource)
|
261
|
+
case hash_or_resource
|
262
|
+
when Stormpath::Resource::Base
|
263
|
+
deep_sanitize hash_or_resource.properties
|
264
|
+
when Hash
|
265
|
+
sanitize hash_or_resource
|
266
|
+
end
|
259
267
|
end
|
260
|
-
end
|
261
268
|
|
262
269
|
end
|
@@ -57,38 +57,58 @@ class Stormpath::Resource::Collection
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def each(&block)
|
60
|
-
|
60
|
+
PaginatedIterator.iterate(collection_href, client, item_class, @criteria, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_page
|
64
|
+
page = CollectionPage.new(collection_href, client, criteria)
|
61
65
|
page.item_type = item_class
|
62
|
-
|
63
|
-
items.each(&block)
|
66
|
+
page
|
64
67
|
end
|
65
68
|
|
66
69
|
private
|
67
70
|
|
68
|
-
|
69
|
-
ITEMS = 'items'
|
71
|
+
module PaginatedIterator
|
70
72
|
|
71
|
-
|
73
|
+
def self.iterate(collection_href, client, item_class, criteria, &block)
|
74
|
+
page = CollectionPage.new collection_href, client, criteria
|
75
|
+
page.item_type = item_class
|
72
76
|
|
73
|
-
|
77
|
+
unless page.items.count.zero?
|
78
|
+
page.items.each(&block)
|
79
|
+
criteria[:offset] = page.offset + page.limit
|
80
|
+
iterate(collection_href, client, item_class, criteria, &block)
|
81
|
+
end
|
82
|
+
end
|
74
83
|
|
75
|
-
def items
|
76
|
-
to_resource_array get_property ITEMS
|
77
84
|
end
|
78
85
|
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
class CollectionPage < Stormpath::Resource::Base
|
87
|
+
ITEMS = 'items'
|
88
|
+
|
89
|
+
prop_accessor :offset, :limit
|
82
90
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
91
|
+
attr_accessor :item_type
|
92
|
+
|
93
|
+
def items
|
94
|
+
to_resource_array get_property(ITEMS)
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_resource properties
|
98
|
+
data_store.instantiate item_type, properties
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_resource_array vals
|
102
|
+
Array.new.tap do |items|
|
103
|
+
if vals.is_a? Array
|
104
|
+
vals.each do |val|
|
105
|
+
resource = to_resource val
|
106
|
+
items << resource
|
107
|
+
end
|
89
108
|
end
|
90
109
|
end
|
91
110
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
111
|
+
|
112
|
+
end#class Stormpath::Resource::Collection::CollectionPage
|
113
|
+
|
114
|
+
end#Stormpath::Resource::Collection
|
@@ -17,11 +17,11 @@ class Stormpath::Resource::CustomData < Stormpath::Resource::Instance
|
|
17
17
|
include Stormpath::Resource::CustomDataHashMethods
|
18
18
|
|
19
19
|
def [](property_name)
|
20
|
-
get_property property_name
|
20
|
+
get_property property_name, ignore_camelcasing: true
|
21
21
|
end
|
22
22
|
|
23
23
|
def []=(property_name, property_value)
|
24
|
-
set_property property_name, property_value
|
24
|
+
set_property property_name, property_value, ignore_camelcasing: true
|
25
25
|
end
|
26
26
|
|
27
27
|
def save
|
@@ -34,7 +34,12 @@ class Stormpath::Resource::CustomData < Stormpath::Resource::Instance
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def delete(name = nil)
|
37
|
-
|
37
|
+
if name.nil?
|
38
|
+
@properties = { HREF_PROP_NAME => @properties[HREF_PROP_NAME] }
|
39
|
+
@dirty_properties.clear
|
40
|
+
@deleted_properties.clear
|
41
|
+
return super()
|
42
|
+
end
|
38
43
|
|
39
44
|
@write_lock.lock
|
40
45
|
property_name = name.to_s
|
@@ -53,7 +58,7 @@ class Stormpath::Resource::CustomData < Stormpath::Resource::Instance
|
|
53
58
|
def sanitize(properties)
|
54
59
|
{}.tap do |sanitized_properties|
|
55
60
|
properties.map do |key, value|
|
56
|
-
property_name = key.to_s
|
61
|
+
property_name = key.to_s
|
57
62
|
sanitized_properties[property_name] = value
|
58
63
|
end
|
59
64
|
end
|
@@ -78,8 +83,9 @@ class Stormpath::Resource::CustomData < Stormpath::Resource::Instance
|
|
78
83
|
end
|
79
84
|
|
80
85
|
def delete_removed_properties
|
81
|
-
@deleted_properties.
|
86
|
+
@deleted_properties.delete_if do |deleted_property_name|
|
82
87
|
data_store.delete self, deleted_property_name
|
88
|
+
true
|
83
89
|
end
|
84
90
|
end
|
85
91
|
|
@@ -4,7 +4,7 @@ module Stormpath::Resource::CustomDataHashMethods
|
|
4
4
|
included do
|
5
5
|
def has_key?(key)
|
6
6
|
materialize unless materialized?
|
7
|
-
properties.has_key? key.to_s
|
7
|
+
properties.has_key? key.to_s
|
8
8
|
end
|
9
9
|
|
10
10
|
alias_method :include?, :has_key?
|
@@ -21,7 +21,7 @@ module Stormpath::Resource::CustomDataHashMethods
|
|
21
21
|
|
22
22
|
def keys
|
23
23
|
materialize unless materialized?
|
24
|
-
properties.keys
|
24
|
+
properties.keys
|
25
25
|
end
|
26
26
|
|
27
27
|
def values
|
@@ -30,7 +30,7 @@ module Stormpath::Resource::CustomDataStorage
|
|
30
30
|
custom_data.send :delete_removed_properties
|
31
31
|
end
|
32
32
|
if custom_data.send :has_new_properties?
|
33
|
-
self.set_property CUSTOM_DATA, custom_data.
|
33
|
+
self.set_property CUSTOM_DATA, custom_data.dirty_properties
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
data/spec/client_spec.rb
CHANGED
@@ -301,7 +301,7 @@ properties
|
|
301
301
|
end
|
302
302
|
|
303
303
|
it 'accepts offset and limit' do
|
304
|
-
expect(test_api_client.applications.limit(2)).to
|
304
|
+
expect(test_api_client.applications.limit(2)).to have_at_least(3).items
|
305
305
|
expect(test_api_client.applications.offset(1).limit(2)).to have_at_least(2).items
|
306
306
|
end
|
307
307
|
|
@@ -578,6 +578,25 @@ properties
|
|
578
578
|
end
|
579
579
|
end
|
580
580
|
|
581
|
+
context 'given a collection with a limit' do
|
582
|
+
let!(:directory_1) do
|
583
|
+
test_api_client.directories.create name: "0000_test_directory_with_limit"
|
584
|
+
end
|
585
|
+
|
586
|
+
let!(:directory_2) do
|
587
|
+
test_api_client.directories.create name: "0001_test_directory_with_limit"
|
588
|
+
end
|
589
|
+
|
590
|
+
after do
|
591
|
+
directory_1.delete if directory_1
|
592
|
+
directory_2.delete if directory_2
|
593
|
+
end
|
594
|
+
|
595
|
+
it 'should retrieve the number of directories described with the limit' do
|
596
|
+
expect(test_api_client.directories).to have_at_least(2).items
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
581
600
|
describe '.create' do
|
582
601
|
let(:directory_attributes) do
|
583
602
|
{
|