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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.rvmrc +2 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/README.md +133 -0
- data/Rakefile +7 -0
- data/bin/autospec +16 -0
- data/bin/htmldiff +16 -0
- data/bin/ldiff +16 -0
- data/bin/restclient +16 -0
- data/bin/rspec +16 -0
- data/lib/usergrid.rb +27 -0
- data/lib/usergrid/core/application.rb +70 -0
- data/lib/usergrid/core/collection.rb +71 -0
- data/lib/usergrid/core/entity.rb +59 -0
- data/lib/usergrid/core/management.rb +37 -0
- data/lib/usergrid/core/organization.rb +51 -0
- data/lib/usergrid/core/resource.rb +117 -0
- data/lib/usergrid/extensions/hash.rb +27 -0
- data/lib/usergrid/extensions/response.rb +64 -0
- data/lib/usergrid/version.rb +3 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/spec_settings.yaml +12 -0
- data/spec/usergrid/core/application_spec.rb +271 -0
- data/spec/usergrid/core/collection_spec.rb +65 -0
- data/spec/usergrid/core/entity_spec.rb +45 -0
- data/spec/usergrid/core/management_spec.rb +36 -0
- data/spec/usergrid/core/organization_spec.rb +72 -0
- data/spec/usergrid/core/resource_spec.rb +47 -0
- data/spec/usergrid/extensions/hash_spec.rb +25 -0
- data/usergrid_iron.gemspec +25 -0
- metadata +178 -0
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|