usergrid_iron 0.0.1

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.
@@ -0,0 +1,59 @@
1
+ # also allows hash or dot notation for entity properties
2
+ module Usergrid
3
+ class Entity < Resource
4
+
5
+ def initialize(url, api_url, options={}, response=nil, index=nil)
6
+ super url, api_url, options, response
7
+ @index = index
8
+ end
9
+
10
+ def data
11
+ get unless response
12
+ @index ? response.entities_data[@index] : response.entity_data
13
+ end
14
+
15
+ def data?
16
+ !!response
17
+ end
18
+
19
+ def resource
20
+ Resource.new url, api_url, options
21
+ end
22
+
23
+ def [](k)
24
+ data[k]
25
+ end
26
+
27
+ def []=(k,v)
28
+ data[k] = v
29
+ end
30
+
31
+ def collection
32
+ Collection.new url[0..url[0..-2].rindex('/')-1], api_url, options
33
+ end
34
+
35
+ def save
36
+ self.put data
37
+ end
38
+
39
+ def to_s
40
+ "resource: #{url}\ndata: #{data.pretty_inspect}"
41
+ end
42
+
43
+ private
44
+
45
+ def method_missing(method, *args, &block)
46
+ if data.respond_to?(method)
47
+ data.send(method, *args, &block)
48
+ elsif method[-1] == '=' && args.size == 1
49
+ data[method[0..-2]] = args[0]
50
+ else
51
+ super method, args, block
52
+ end
53
+ end
54
+
55
+ def respond_to?(method)
56
+ super.respond_to?(method) || data.respond_to?(method)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ module Usergrid
2
+ class Management < Resource
3
+
4
+ def initialize(api_url, options)
5
+ url = concat_urls(api_url, 'management')
6
+ super url, api_url, options
7
+ end
8
+
9
+ # one way: cannot delete organizations
10
+ def create_organization(organization, username, name, email, password)
11
+ data = { organization: organization,
12
+ username: username,
13
+ name: name,
14
+ email: email,
15
+ password: password }
16
+ self['organizations'].post data
17
+ end
18
+
19
+ def organizations
20
+ self[__method__].get
21
+ end
22
+
23
+ def organization(organization)
24
+ url = self["organizations/#{organization}"].url
25
+ Organization.new url, api_url, options
26
+ end
27
+
28
+ def users
29
+ self['users'].get
30
+ end
31
+
32
+ def user(name_or_uuid)
33
+ self["users/#{name_or_uuid}"].get
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ require 'uri'
2
+ module Usergrid
3
+ class Organization < Resource
4
+
5
+ def initialize(url, api_url, options)
6
+ super url, api_url, options
7
+ end
8
+
9
+ def name
10
+ URI(url).path.split('/').last
11
+ end
12
+
13
+ def create_application(name)
14
+ self['applications'].post({ name: name })
15
+ application name
16
+ end
17
+
18
+ def applications(query=nil)
19
+ resource = self[__method__]
20
+ response = query ? resource.query(query) : resource.get
21
+ response.data['data'].collect do |k|
22
+ application concat_urls(api_url, k)
23
+ end
24
+ end
25
+
26
+ def application(name_or_uuid)
27
+ Usergrid::Application.new concat_urls(api_url, "#{name}/#{name_or_uuid}"), api_url, options
28
+ end
29
+
30
+ def users(query=nil)
31
+ self[__method__].query(query)
32
+ end
33
+
34
+ def user(user)
35
+ management.user(user)
36
+ end
37
+
38
+ def feed(query=nil)
39
+ self[__method__].query(query)
40
+ end
41
+
42
+ def credentials
43
+ self[__method__].get
44
+ end
45
+
46
+ def generate_credentials
47
+ self['credentials'].post nil
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,117 @@
1
+ require 'rest_client'
2
+
3
+ module Usergrid
4
+ class Resource < RestClient::Resource
5
+
6
+ DEFAULT_API_URL = 'https://api.usergrid.com'
7
+ TYPE_HEADERS = { :content_type => :json, :accept => :json }
8
+
9
+ attr_reader :current_user, :auth_token, :api_url
10
+
11
+ def initialize(resource_url=DEFAULT_API_URL, api_url=nil, options={}, response=nil)
12
+ options[:headers] = TYPE_HEADERS.merge options[:headers] || {}
13
+ @api_url = api_url || resource_url
14
+ self.response = response
15
+ super resource_url, options, &method(:handle_response)
16
+ end
17
+
18
+ # gets user token and automatically set auth header for future requests
19
+ # precondition: resource must already be set to the correct context (application or management)
20
+ def login(username, password)
21
+ params = { grant_type: "password", username: username, password: password }
22
+ response = self['token'].get({ params: params })
23
+ self.auth_token = response.data['access_token']
24
+ user_uuid = response.data['user']['uuid']
25
+ @current_user = self["/users/#{user_uuid}"].get.entity
26
+ response
27
+ end
28
+
29
+ # remove auth header for future requests
30
+ # only affects self and derivative resources
31
+ def logout
32
+ self.auth_token = nil
33
+ @current_user = nil
34
+ end
35
+
36
+ def logged_in?
37
+ !!@auth_token
38
+ end
39
+
40
+ def management
41
+ Usergrid::Management.new api_url, options
42
+ end
43
+
44
+ # application defaults to sandbox if none provided
45
+ def application(organization, application='sandbox')
46
+ Usergrid::Application.new concat_urls(api_url, "#{organization}/#{application}"), api_url, options
47
+ end
48
+
49
+ def query(query=nil, options={})
50
+ options = options.merge({ql: query}) if query
51
+ get({params: options})
52
+ end
53
+
54
+ def entity
55
+ response.entity
56
+ end
57
+
58
+ def collection
59
+ Collection.new url, api_url, options, response
60
+ end
61
+
62
+ # overridden to ensure sub resources are instances of this class
63
+ def [](suburl, &new_block)
64
+ case
65
+ when block_given? then Resource.new(concat_urls(url, suburl), api_url, options, &new_block)
66
+ when block then Resource.new(concat_urls(url, suburl), api_url, options, &block)
67
+ else
68
+ Resource.new(concat_urls(url, suburl), api_url, options)
69
+ end
70
+ end
71
+
72
+ def api_resource(suburl)
73
+ Resource.new(concat_urls(api_url, suburl), api_url, options)
74
+ end
75
+
76
+ def get(additional_headers={}, &block)
77
+ self.response = super additional_headers, &block
78
+ end
79
+
80
+ def post(payload, additional_headers={}, &block)
81
+ payload = payload.to_json if payload.is_a?(Hash) || payload.is_a?(Array)
82
+ self.response = super payload, additional_headers, &block
83
+ end
84
+
85
+ def put(payload, additional_headers={}, &block)
86
+ payload = payload.to_json if payload.is_a?(Hash) || payload.is_a?(Array)
87
+ self.response = super payload, additional_headers, &block
88
+ end
89
+
90
+ protected
91
+
92
+ attr_reader :response
93
+
94
+ def response=(response)
95
+ @response = response
96
+ end
97
+
98
+ def auth_token=(auth_token)
99
+ @auth_token = auth_token
100
+ if auth_token
101
+ @options[:headers].merge!({ Authorization: "Bearer #{auth_token}" })
102
+ else
103
+ @options[:headers].delete :Authorization if @options
104
+ end
105
+ end
106
+
107
+ # add verbose debugging of response body
108
+ def handle_response(response, request, result, &block)
109
+ LOG.debug "response.body = #{response}"
110
+ response = response.return!(request, result, &block)
111
+ response.resource = self
112
+ self.response = response
113
+ response
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,27 @@
1
+ class Hash
2
+
3
+ # recursive
4
+ def add_dot_notation!
5
+ add_dot_notation_recurse! self
6
+ end
7
+
8
+ # not recursive
9
+ def symbolize_keys
10
+ inject({}) do |options, (key, value)|
11
+ options[(key.to_sym rescue key) || key] = value
12
+ options
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def add_dot_notation_recurse!(_hash)
19
+ _hash.each do |k,v|
20
+ getter = k.to_sym; setter = "#{k}=".to_sym
21
+ _hash.define_singleton_method getter, lambda { _hash[k] } unless _hash.respond_to? getter
22
+ _hash.define_singleton_method setter, lambda { |v| _hash[k] = v } unless _hash.respond_to? setter
23
+ add_dot_notation_recurse!(v) if v.is_a? Hash
24
+ v.each { |e| add_dot_notation_recurse!(e) if e.is_a? Hash } if v.is_a? Array
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ module RestClient
2
+ module Response
3
+
4
+ def resource=(resource)
5
+ @resource = resource
6
+ end
7
+
8
+ def resource
9
+ @resource
10
+ end
11
+
12
+ def data
13
+ @data = JSON.parse(self).add_dot_notation! unless @data
14
+ @data
15
+ end
16
+
17
+ def collection
18
+ resource.collection
19
+ end
20
+
21
+ def multiple_entities?
22
+ entities_data = data['entities'] || data['data'] || data['messages']
23
+ entities_data.is_a? Array
24
+ end
25
+
26
+ def entities_data
27
+ return @entities_data if @entities_data
28
+ entities_data = data['entities'] || data['data'] || data['messages']
29
+ raise "unable to determine entities from: #{data}" unless entities_data.is_a?(Array)
30
+ entities_data.each do |e|
31
+ e['uri'] = resource.concat_urls(data['uri'], e['uuid']) if e['uuid']
32
+ end
33
+ @entities_data = entities_data
34
+ end
35
+
36
+ def entities
37
+ return @entities if @entities
38
+ index = -1
39
+ @entities = entities_data.collect do |e|
40
+ Usergrid::Entity.new e['uri'], resource.api_url, resource.options, self, index+=1
41
+ end
42
+ end
43
+
44
+ def entity_data
45
+ if multiple_entities?
46
+ entities_data.first
47
+ elsif data['data']
48
+ d = data['data']
49
+ d['uri'] = @resource.url
50
+ d
51
+ elsif data['organization']
52
+ d = data['organization']
53
+ d['uri'] = @resource.url
54
+ d
55
+ else
56
+ entities_data.first
57
+ end
58
+ end
59
+
60
+ def entity
61
+ Usergrid::Entity.new entity_data['uri'], resource.api_url, resource.options, self
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module Usergrid
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,77 @@
1
+ require 'simplecov'
2
+
3
+ require 'rspec'
4
+ require 'yaml'
5
+ require 'securerandom'
6
+ require_relative '../lib/usergrid'
7
+
8
+ LOG = Logger.new(STDOUT)
9
+ RestClient.log=LOG
10
+
11
+ SimpleCov.at_exit do
12
+ SimpleCov.result.format!
13
+ #index = File.join(SimpleCov.coverage_path, 'index.html')
14
+ #`open #{index}` if File.exists?(index)
15
+ end
16
+ SimpleCov.start
17
+
18
+ SPEC_SETTINGS = YAML::load_file(File.join File.dirname(__FILE__), 'spec_settings.yaml')
19
+
20
+ # ensure we are correctly setup (management login & organization)
21
+ management = Usergrid::Resource.new(SPEC_SETTINGS[:api_url]).management
22
+ management.login SPEC_SETTINGS[:management][:username], SPEC_SETTINGS[:management][:password]
23
+
24
+ begin
25
+ management.create_organization(SPEC_SETTINGS[:organization][:name],
26
+ SPEC_SETTINGS[:organization][:username],
27
+ SPEC_SETTINGS[:organization][:username],
28
+ "#{SPEC_SETTINGS[:organization][:username]}@email.com",
29
+ SPEC_SETTINGS[:organization][:password])
30
+ LOG.info "created organization with user #{SPEC_SETTINGS[:organization][:username]}@email.com"
31
+ rescue
32
+ if JSON($!.response)['error'] == "duplicate_unique_property_exists"
33
+ LOG.debug "test organization exists"
34
+ else
35
+ raise $!
36
+ end
37
+ end
38
+
39
+ def app_endpoint
40
+ "#{SPEC_SETTINGS[:organization][:name]}/#{SPEC_SETTINGS[:application][:name]}"
41
+ end
42
+
43
+ def org_endpoint
44
+ "#{SPEC_SETTINGS[:organization][:name]}"
45
+ end
46
+
47
+ def create_random_application
48
+ management = login_management
49
+ organization = management.organization SPEC_SETTINGS[:organization][:name]
50
+
51
+ app_name = "_test_app_#{SecureRandom.hex}"
52
+ organization.create_application app_name
53
+ management.application SPEC_SETTINGS[:organization][:name], app_name
54
+ end
55
+
56
+ def delete_application(application)
57
+ management = login_management
58
+ application.auth_token = management.auth_token
59
+ application.delete
60
+ end
61
+
62
+ def create_random_user(application, login=false)
63
+ random = SecureRandom.hex
64
+ user_hash = {username: "username_#{random}",
65
+ name: "#{random} name",
66
+ email: "#{random}@email.com",
67
+ password: random}
68
+ entity = application['users'].post(user_hash).entity
69
+ application.login user_hash[:username], user_hash[:password] if login
70
+ entity
71
+ end
72
+
73
+ def login_management
74
+ management = Usergrid::Resource.new(SPEC_SETTINGS[:api_url]).management
75
+ management.login SPEC_SETTINGS[:organization][:username], SPEC_SETTINGS[:organization][:password]
76
+ management
77
+ end