class Stormpath::DataStore

Constants

CACHE_REGIONS
DEFAULT_API_VERSION
DEFAULT_BASE_URL
DEFAULT_SERVER_HOST
HREF_PROP_NAME

Attributes

api_key[R]
base_url[R]
cache_manager[R]
client[R]
request_executor[R]

Public Class Methods

new(request_executor, api_key, cache_opts, client, base_url = nil) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
31 def initialize(request_executor, api_key, cache_opts, client, base_url = nil)
32   assert_not_nil request_executor, 'RequestExecutor cannot be null.'
33 
34   @client = client
35   @base_url = base_url || DEFAULT_BASE_URL
36   @request_executor = request_executor
37   @api_key = api_key
38   initialize_cache(cache_opts)
39 end

Public Instance Methods

create(parent_href, resource, return_type, options = {}) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
66 def create(parent_href, resource, return_type, options = {})
67   # TODO: assuming there is no ? in url
68   parent_href = "#{parent_href}?#{URI.encode_www_form(options)}" unless options.empty?
69 
70   save_resource(parent_href, resource, return_type).tap do |returned_resource|
71     if resource.is_a?(return_type)
72       resource.set_properties(returned_resource.properties)
73     end
74   end
75 end
delete(resource, property_name = nil) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
101 def delete(resource, property_name = nil)
102   assert_not_nil(resource, 'resource argument cannot be null.')
103   assert_kind_of(
104     Stormpath::Resource::Base,
105     resource,
106     'resource argument must be instance of Stormpath::Resource::Base'
107   )
108 
109   href = resource.href
110   href += "/#{property_name}" if property_name
111   href = qualify(href)
112 
113   execute_request('delete', href)
114   clear_cache_on_delete(href)
115   nil
116 end
execute_raw_request(href, body, klass) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
118 def execute_raw_request(href, body, klass)
119   request = Request.new('POST', href, nil, {}, body.to_json, @api_key)
120   apply_default_request_headers(request)
121   response = @request_executor.execute_request(request)
122   result = !response.body.empty? ? MultiJson.load(response.body) : ''
123 
124   if response.error?
125     error = Stormpath::Resource::Error.new(result)
126     raise Stormpath::Error, error
127   end
128 
129   cache_walk(result)
130   instantiate(klass, result)
131 end
get_resource(href, clazz, query = nil) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
56 def get_resource(href, clazz, query = nil)
57   q_href = qualify href
58 
59   data = execute_request('get', q_href, nil, query)
60 
61   clazz = clazz.call(data) if clazz.respond_to? :call
62 
63   instantiate(clazz, data.to_hash)
64 end
initialize_cache(cache_opts) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
41 def initialize_cache(cache_opts)
42   @cache_manager = Stormpath::Cache::CacheManager.new
43   regions_opts = cache_opts[:regions] || {}
44   CACHE_REGIONS.each do |region|
45     region_opts = regions_opts[region.to_sym] || {}
46     region_opts[:store] ||= cache_opts[:store]
47     region_opts[:store_opts] ||= cache_opts[:store_opts]
48     @cache_manager.create_cache(region, region_opts)
49   end
50 end
instantiate(clazz, properties = {}) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
52 def instantiate(clazz, properties = {})
53   clazz.new(properties, client)
54 end
save(resource, clazz = nil) click to toggle source
   # File lib/stormpath-sdk/data_store.rb
77 def save(resource, clazz = nil)
78   assert_not_nil(resource, 'resource argument cannot be null.')
79   assert_kind_of(
80     Stormpath::Resource::Base,
81     resource,
82     'resource argument must be instance of Stormpath::Resource::Base'
83   )
84   href = resource.href
85   assert_not_nil(href, 'href or resource.href cannot be null.')
86   assert_true(
87     !href.empty?,
88     'save may only be called on objects that have already been persisted'\
89     ' (i.e. they have an existing href).'
90   )
91 
92   href = qualify(href)
93 
94   clazz ||= resource.class
95 
96   save_resource(href, resource, clazz).tap do |return_value|
97     resource.set_properties(return_value)
98   end
99 end

Private Instance Methods

apply_default_request_headers(request) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
238 def apply_default_request_headers(request)
239   request.http_headers.store('Accept', 'application/json')
240   apply_default_user_agent(request)
241 
242   if request.body && !request.body.empty?
243     request.http_headers.store('Content-Type', 'application/json')
244   end
245 end
apply_default_user_agent(request) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
252 def apply_default_user_agent(request)
253   request.http_headers.store(
254     'User-Agent', 'stormpath-sdk-ruby/' + Stormpath::VERSION +
255     " ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}" \
256     ' ' + Gem::Platform.local.os.to_s + '/' + Gem::Platform.local.version.to_s
257   )
258 end
apply_form_data_request_headers(request) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
247 def apply_form_data_request_headers(request)
248   request.http_headers.store('Content-Type', 'application/x-www-form-urlencoded')
249   apply_default_user_agent(request)
250 end
cache(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
219 def cache(resource)
220   cache = cache_for(resource[HREF_PROP_NAME])
221   cache.put(resource[HREF_PROP_NAME], resource) if cache
222 end
cache_for(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
224 def cache_for(href)
225   @cache_manager.get_cache(region_for(href))
226 end
cache_walk(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
198 def cache_walk(resource)
199   assert_not_nil(resource[HREF_PROP_NAME], "resource must have 'href' property")
200   items = resource['items']
201 
202   if items # collection resource
203     resource['items'] = items.map do |item|
204       cache_walk(item)
205       { HREF_PROP_NAME => item[HREF_PROP_NAME] }
206     end
207   else     # single resource
208     resource.each do |attr, value|
209       next unless value.is_a?(Hash) && value[HREF_PROP_NAME]
210       walked = cache_walk(value)
211       resource[attr] = { HREF_PROP_NAME => value[HREF_PROP_NAME] }
212       resource[attr]['items'] = walked['items'] if walked['items']
213     end
214     cache(resource) if resource.length > 1
215   end
216   resource
217 end
clear_application_cache_on_account_store_save(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
295 def clear_application_cache_on_account_store_save(resource)
296   if resource.new?
297     if resource.default_account_store? == true || resource.default_group_store? == true
298       clear_cache(resource.application.href)
299     end
300   else
301     if !resource.dirty_properties['isDefaultAccountStore'].nil? || !resource.dirty_properties['isDefaultGroupStore'].nil?
302       clear_cache(resource.application.href)
303     end
304   end
305 end
clear_cache(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
193 def clear_cache(href)
194   cache = cache_for(href)
195   cache.delete(href) if cache
196 end
clear_cache_on_delete(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
182 def clear_cache_on_delete(href)
183   if href =~ custom_data_delete_field_url_regex
184     href = href.split('/')[0..-2].join('/')
185   end
186   clear_cache(href)
187 end
clear_cache_on_save(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
280 def clear_cache_on_save(resource)
281   if resource.is_a?(Stormpath::Resource::CustomDataStorage)
282     clear_custom_data_cache_on_custom_data_storage_save(resource)
283   elsif resource.is_a?(Stormpath::Resource::AccountStoreMapping)
284     clear_application_cache_on_account_store_save(resource)
285   end
286 end
clear_custom_data_cache_on_custom_data_storage_save(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
288 def clear_custom_data_cache_on_custom_data_storage_save(resource)
289   if resource.dirty_properties.key?('customData') && (resource.new? == false)
290     cached_href = resource.href + '/customData'
291     clear_cache(cached_href)
292   end
293 end
custom_data_delete_field_url_regex() click to toggle source
    # File lib/stormpath-sdk/data_store.rb
189 def custom_data_delete_field_url_regex
190   /#{@base_url}\/(accounts|groups)\/\w+\/customData\/\w+[\/]{0,1}$/
191 end
execute_request(http_method, href, resource = nil, query = nil) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
143 def execute_request(http_method, href, resource = nil, query = nil)
144   if http_method == 'get' && (cache = cache_for href)
145     cached_result = cache.get(href)
146     return cached_result if cached_result
147   end
148 
149   body = extract_body_from_resource(resource)
150 
151   request = Request.new(http_method, href, query, {}, body, @api_key)
152 
153   if resource.try(:form_data?)
154     apply_form_data_request_headers(request)
155   else
156     apply_default_request_headers(request)
157   end
158 
159   response = @request_executor.execute_request(request)
160 
161   result = !response.body.empty? ? MultiJson.load(response.body) : ''
162 
163   if response.error?
164     error = Stormpath::Resource::Error.new(result)
165     raise Stormpath::Error, error
166   end
167 
168   if resource.is_a?(Stormpath::Provider::AccountAccess)
169     is_new_account = response.http_status == 201
170     result = { is_new_account: is_new_account, account: result }
171   end
172 
173   return if http_method == 'delete'
174 
175   if result[HREF_PROP_NAME] && !resource_is_saml_mapping_rules?(resource) && !user_info_mapping_rules?(resource)
176     cache_walk result
177   else
178     result
179   end
180 end
extract_body_from_resource(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
307 def extract_body_from_resource(resource)
308   return if resource.nil?
309   form_data = resource.try(:form_data?)
310 
311   if form_data
312     form_request_parse(resource)
313   else
314     MultiJson.dump(to_hash(resource))
315   end
316 end
form_request_parse(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
318 def form_request_parse(resource)
319   URI.encode_www_form(resource.form_properties.to_a)
320 end
needs_to_be_fully_qualified?(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
135 def needs_to_be_fully_qualified?(href)
136   !href.downcase.start_with?('http')
137 end
parse_response(response) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
275 def parse_response(response)
276   return {} if response.is_a?(String) && response.blank?
277   response.to_hash
278 end
qualify(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
139 def qualify(href)
140   needs_to_be_fully_qualified?(href) ? @base_url + href : href
141 end
region_for(href) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
228 def region_for(href)
229   return nil if href.nil?
230   region = if href.include?('/customData')
231              href.split('/')[-1]
232            else
233              href.split('/')[-2]
234            end
235   CACHE_REGIONS.include?(region) ? region : nil
236 end
resource_is_application_web_config(resource, name) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
366 def resource_is_application_web_config(resource, name)
367   resource.is_a?(Stormpath::Resource::ApplicationWebConfig) &&
368     Stormpath::Resource::ApplicationWebConfig::ENDPOINTS.include?(name.underscore.to_sym)
369 end
resource_is_custom_data(resource, name) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
362 def resource_is_custom_data(resource, name)
363   resource.is_a?(Stormpath::Resource::CustomData) || name == 'customData'
364 end
resource_is_saml_mapping_rules?(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
371 def resource_is_saml_mapping_rules?(resource)
372   resource.is_a?(Stormpath::Resource::AttributeStatementMappingRules)
373 end
resource_nested_submittable(resource, name) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
356 def resource_nested_submittable(resource, name)
357   ['provider', 'providerData', 'accountStore'].include?(name) ||
358     resource_is_custom_data(resource, name) ||
359     resource_is_application_web_config(resource, name)
360 end
save_resource(href, resource, return_type) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
260 def save_resource(href, resource, return_type)
261   assert_not_nil(resource, 'resource argument cannot be null.')
262   assert_not_nil(return_type, 'returnType class cannot be null.')
263   assert_kind_of(
264     Stormpath::Resource::Base,
265     resource,
266     'resource argument must be instance of Stormpath::Resource::Base'
267   )
268 
269   q_href = qualify(href)
270   clear_cache_on_save(resource)
271   response = execute_request('post', q_href, resource)
272   instantiate(return_type, parse_response(response))
273 end
to_hash(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
322 def to_hash(resource)
323   {}.tap do |properties|
324     resource.get_dirty_property_names.each do |name|
325       ignore_camelcasing = resource_is_custom_data(resource, name)
326       property = resource.get_property name, ignore_camelcasing: ignore_camelcasing
327 
328       # Special use cases are with Custom Data, Provider and ProviderData, their hashes should not be simplified
329       # As of the implementation for MFA, Phone resource is added too
330       if property.is_a?(Hash) && !resource_nested_submittable(resource, name) && name != 'items' && name != 'phone'
331         property = to_simple_reference(name, property)
332       end
333 
334       if name == 'items' && resource_is_saml_mapping_rules?(resource)
335         property = property.map do |item|
336           item.transform_keys { |key| key.to_s.camelize(:lower).to_sym }
337         end
338       end
339 
340       properties.store(name, property)
341     end
342   end
343 end
to_simple_reference(property_name, hash) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
345 def to_simple_reference(property_name, hash)
346   assert_true(
347     hash.key?(HREF_PROP_NAME),
348     "Nested resource '#{property_name}' must have an 'href' property."
349   )
350 
351   href = hash[HREF_PROP_NAME]
352 
353   { HREF_PROP_NAME => href }
354 end
user_info_mapping_rules?(resource) click to toggle source
    # File lib/stormpath-sdk/data_store.rb
375 def user_info_mapping_rules?(resource)
376   resource.is_a?(Stormpath::Resource::UserInfoMappingRules)
377 end