stormpath-sdk 1.0.0.beta.8 → 1.0.0.beta.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/CHANGES.md +11 -0
  4. data/README.md +1 -0
  5. data/lib/stormpath-sdk/auth/basic_authenticator.rb +0 -2
  6. data/lib/stormpath-sdk/client.rb +2 -0
  7. data/lib/stormpath-sdk/data_store.rb +45 -5
  8. data/lib/stormpath-sdk/http/authc/sauthc1_signer.rb +1 -1
  9. data/lib/stormpath-sdk/http/http_client_request_executor.rb +4 -0
  10. data/lib/stormpath-sdk/http/request.rb +1 -1
  11. data/lib/stormpath-sdk/id_site/error.rb +42 -0
  12. data/lib/stormpath-sdk/id_site/id_site_result.rb +6 -1
  13. data/lib/stormpath-sdk/oauth/authenticator.rb +26 -0
  14. data/lib/stormpath-sdk/oauth/password_grant.rb +17 -0
  15. data/lib/stormpath-sdk/oauth/password_grant_request.rb +13 -0
  16. data/lib/stormpath-sdk/oauth/refresh_grant_request.rb +12 -0
  17. data/lib/stormpath-sdk/oauth/refresh_token.rb +16 -0
  18. data/lib/stormpath-sdk/oauth/verify_access_token.rb +15 -0
  19. data/lib/stormpath-sdk/oauth/verify_token.rb +7 -0
  20. data/lib/stormpath-sdk/resource/access_token.rb +12 -0
  21. data/lib/stormpath-sdk/resource/account.rb +1 -0
  22. data/lib/stormpath-sdk/resource/application.rb +31 -6
  23. data/lib/stormpath-sdk/resource/oauth_policy.rb +5 -0
  24. data/lib/stormpath-sdk/resource/organization.rb +12 -0
  25. data/lib/stormpath-sdk/resource/organization_account_store_mapping.rb +6 -0
  26. data/lib/stormpath-sdk/resource/verification_email.rb +5 -0
  27. data/lib/stormpath-sdk/version.rb +2 -2
  28. data/lib/stormpath-sdk.rb +17 -1
  29. data/spec/client_spec.rb +29 -0
  30. data/spec/resource/account_spec.rb +13 -0
  31. data/spec/resource/application_spec.rb +243 -3
  32. data/spec/resource/directory_spec.rb +9 -0
  33. data/spec/resource/organization_spec.rb +185 -0
  34. data/spec/support/custom_data_storage_behavior.rb +2 -2
  35. data/stormpath-sdk.gemspec +1 -1
  36. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 217ba3dfe6d6347582c6a2c428ca2c0ab357b434
4
- data.tar.gz: 9e8e70ef785bc057c5c25240ad2a40691992d06f
3
+ metadata.gz: ffd1ce3b14483c0ba0f564a704d5e7d6d079a99e
4
+ data.tar.gz: b59460eaea481ca8e83d4a4bf4accb8728481554
5
5
  SHA512:
6
- metadata.gz: d4d3e8df8df4fc6812d96dc0eb55e776f149d5400c038d5187067d0e87362277b1441cb933505f8996323a4a0e6ac8b3777ea7d5701c278ee9c24531783ba7f5
7
- data.tar.gz: 2c1431cf95b22b5ab3ee0b8bd8881a0edefcc6c446f3674e97b0a624752a6896a7314fa2e4c43c6b7d477178317f3c1951aac55b483599cdfbb927d28f50db6c
6
+ metadata.gz: 6fa8d912dd6323c2dcfe19d08bbc7a2efce1c8eea0d74ab2f34dfbbb1d891e78126ee4022045bc4d39faae429a98784ec9cfdd479cd920eafca443271cd10d32
7
+ data.tar.gz: 08e1230337d60e8e55026ca367ac2103cd9c5414a1cc075301384d8550b78a1b2f2f35ea6001bd60296e03e2715582fc3fff77c516fb04924aece923a15a70ce
data/.travis.yml CHANGED
@@ -7,8 +7,8 @@ services:
7
7
  - redis-server
8
8
  env:
9
9
  global:
10
- - secure: cfX/Vagk7SskUp1cnuTTfQHNWz6pjx7bHJOa25ahk/3Jvsqz37qf8MLNs8uRUb/LN63G/YNUtrcRZQiyDS9WHehQy0p7IO68UuOG4zqkJE0iemR0kToCTHMbyLTOB70nhTuwmRfh1KeT5Ja3D9TOtApQErU5IQaKm5jP8CZb4PA=
11
- - secure: Vhb4qkFc0BcRkJaPU6ZbM9vPHaEHoz/A1LlQ1IMrEdXS/nUabd4l32q6zjJZvfHJ5bI1PXgk1BFztVGT65UT7Uu17KKawzLZWDLmrgzRESkKDj/Ld9Wg79DY6ooJ/juWBrWuJtoNOFKy6CqLdCKWIzNkd9zG+au3qoFP8LfhRh4=
12
- - secure: dKmkzv90Fn1JQpSc2l+cESLFYw3bnN5TsgDKTc2tFFi285EJuqd2z22wfDGcaYAoqX/ck+YTdPqVH6trrC7b3pSMqJSBEaHtWiYMbEkmf/QWrVAHy4LEKFAcs0oACjwVRe7CGBu8RRBWcl8I1STpYm11S8WDe8Y/GHo0HnXipHo=
13
- - secure: FejMHUo69w52zjPBMfUThhhgj7md/dj+7gf+1d0sgDuDfZ+gECEyHF8iWvkm64k3j+PX4E/y44HdV1+qIMWTGNA0xSZNFEHBBJrEC1BRKm9BkT8W0KBcupmLRHW0BtLWMrqtKOgOyDEdoufuLx7wDpTNslPeGJ4NUZIGEDTuwLc=
14
- - secure: DyEw82o0ozA9rbbgYUk8jiC/KNwB0x0OuVv/TX7Xso3uXgfTL1m3IWYLDX6kvV4QIvHNaNdj1g02ddnRwZwuvA3IH81J8+mkZ6aIXTS1YKZPEZMSqewZNOGQPRVaUOeQ9ymQtE7bfxWkViF2JzJlGzc3IxYUKHeo+NE/Hgehuz4=
10
+ - secure: MeyjZGgySZvpYVRm2i7wkrhvu9KUeU7eQ5aKj7FXqIYlQe3T67k+KKA3Ejp6WC3wUEVPUFseWMZCuNkRc0UeGA5/4e4LLc++XuaZn1jLTm1yNofh/CFAAjt5VdIYz4R7sKxpyLxs0orK2+HcaiCoqSDj7ehw2SlDca9VEi0GoQk=
11
+ - secure: MrtbhfH1IfwDkkvf0pq6trgj68to/fK4c+L1daKvMaNiNvwggbA3s0ea9QjHxXfWmPqL5bf8Q5N7YqXUw8cLpRPrKUA65JkyhyzIju8FgzXz83aCvjJD+5XhJIGzpLM8qHeKh7F0K6/iURTKIUgZXbguK4HpEeCMrrdPYcof3Ew=
12
+ - secure: JChx6k5NOw/PBzH6gpHdqxHPy8hpaTALVs2riTVXorJZ5p06F3riqFBQbMh6REzXdJLjD6VKPORt19WOkmLHCPW8x0g7HxIRHT0DCDLX/4980dZZAev3blSvfJ7t1cWlBVsZb0LgVEkswvKdSYEZvDQTy5XlWsIMuNhHUclsTZk=
13
+ - secure: c5tUXb7FPMDD/KkpDwYNfnZ2k0N0RltBAQt1IYOFkdcztIAdcGmWPtT4l07He+UJiF2Vy92KrsSK709FFDwdxAleSgFKwpCrtgJRXXqRqT/gDiJUsGU1jC4QgXpu/QWCWsCSs/v1l1GzZyZF61aQzqINVrGwF5n2/MeMGOAJkaA=
14
+ - secure: SepFOaSOjRr5EJLBlXKT60FgSmKZ604zhhDaes+s9rQgJcaUsVkTxFYhkE6mkDadH7dZ6ACW1TaWWTmFm+JMFuli/bcyvX9wm5akWM6EF3BdJ8djMac34iJuTB3MWED+fOaFco9oZjMQOYZlSu9nS4VOvH0ekcTnQnThzxYxpfs=
data/CHANGES.md CHANGED
@@ -1,6 +1,17 @@
1
1
  stormpath-sdk-ruby Changelog
2
2
  ============================
3
3
 
4
+ Version 1.0.0.beta.9
5
+ --------------------
6
+
7
+ Released on December 2, 2015
8
+
9
+ - Organization CRUD
10
+ - Token Management
11
+ - Ability to specify an organization nameKey as an accountStore for loginAttempt
12
+ - Get applications for an account
13
+ - Resending email verification
14
+
4
15
  Version 1.0.0.beta.8
5
16
  --------------------
6
17
 
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Build Status](https://api.travis-ci.org/stormpath/stormpath-sdk-ruby.png?branch=master,development)](https://travis-ci.org/stormpath/stormpath-sdk-ruby)
2
+ [![Code Climate](https://codeclimate.com/github/stormpath/stormpath-sdk-ruby/badges/gpa.svg)](https://codeclimate.com/github/stormpath/stormpath-sdk-ruby)
2
3
 
3
4
  # Stormpath Ruby SDK
4
5
 
@@ -45,9 +45,7 @@ module Stormpath
45
45
  href = parent_href + '/loginAttempts'
46
46
 
47
47
  @data_store.create href, attempt, AuthenticationResult
48
-
49
48
  end
50
-
51
49
  end
52
50
  end
53
51
  end
@@ -53,9 +53,11 @@ module Stormpath
53
53
  data_store.save token, Stormpath::Resource::Account
54
54
  end
55
55
  end
56
+ has_many :organizations, href: '/organizations', can: [:get, :create]
56
57
  has_many :groups, href: '/groups', can: :get
57
58
  has_many :group_memberships, href: '/groupMemberships', can: [:get, :create]
58
59
  has_many :account_store_mappings, href: '/accountStoreMappings', can: [:get, :create]
60
+ has_many :organization_account_store_mappings, href: '/organizationAccountStoreMappings', can: [:get, :create]
59
61
 
60
62
  private
61
63
 
@@ -115,12 +115,16 @@ class Stormpath::DataStore
115
115
  return cached_result if cached_result
116
116
  end
117
117
 
118
- body = if resource
119
- MultiJson.dump(to_hash(resource))
120
- end
118
+ body = extract_body_from_resource(resource)
121
119
 
122
120
  request = Request.new(http_method, href, query, Hash.new, body, @api_key)
123
- apply_default_request_headers request
121
+
122
+ if resource.try(:form_data?)
123
+ apply_form_data_request_headers request
124
+ else
125
+ apply_default_request_headers request
126
+ end
127
+
124
128
  response = @request_executor.execute_request request
125
129
 
126
130
  result = response.body.length > 0 ? MultiJson.load(response.body) : ''
@@ -209,6 +213,11 @@ class Stormpath::DataStore
209
213
  request.http_headers.store 'Content-Type', 'application/json'
210
214
  end
211
215
  end
216
+
217
+ def apply_form_data_request_headers(request)
218
+ request.http_headers.store 'Content-Type', 'application/x-www-form-urlencoded'
219
+ request.http_headers.store 'User-Agent', 'Stormpath-RubySDK/' + Stormpath::VERSION
220
+ end
212
221
 
213
222
  def save_resource(href, resource, return_type)
214
223
  assert_not_nil resource, "resource argument cannot be null."
@@ -221,7 +230,12 @@ class Stormpath::DataStore
221
230
 
222
231
  response = execute_request 'post', q_href, resource
223
232
 
224
- instantiate return_type, response.to_hash
233
+ instantiate return_type, parse_response(response)
234
+ end
235
+
236
+ def parse_response(response)
237
+ return {} if response.is_a? String and response.blank?
238
+ response.to_hash
225
239
  end
226
240
 
227
241
  def clear_cache_on_save(resource)
@@ -252,6 +266,32 @@ class Stormpath::DataStore
252
266
  end
253
267
  end
254
268
 
269
+ def extract_body_from_resource(resource)
270
+ return if resource.nil?
271
+ form_data = resource.try(:form_data?)
272
+
273
+ if form_data
274
+ form_request_parse(resource)
275
+ else
276
+ MultiJson.dump(to_hash(resource))
277
+ end
278
+ end
279
+
280
+ def form_request_parse(resource)
281
+ data = ""
282
+
283
+ property_names = resource.get_dirty_property_names
284
+ property_names.each do |name|
285
+ if name != "formData"
286
+ property = resource.get_property name, ignore_camelcasing: true
287
+ data += name.underscore + '=' + property.to_s
288
+ data += '&' unless name == property_names.last
289
+ end
290
+ end
291
+
292
+ data
293
+ end
294
+
255
295
  def to_hash(resource)
256
296
  Hash.new.tap do |properties|
257
297
  resource.get_dirty_property_names.each do |name|
@@ -189,4 +189,4 @@ module Stormpath
189
189
  end#Sauthc1Signer
190
190
  end#Authc
191
191
  end#Http
192
- end#Stormpath
192
+ end#Stormpath
@@ -36,6 +36,10 @@ module Stormpath
36
36
  else
37
37
  request.href
38
38
  end
39
+
40
+ if request.http_headers["Content-Type"] == "application/x-www-form-urlencoded"
41
+ @http_client.set_auth(request.href, request.api_key.id, request.api_key.secret)
42
+ end
39
43
 
40
44
  method = @http_client.method(request.http_method.downcase)
41
45
 
@@ -63,7 +63,7 @@ module Stormpath
63
63
  enc_value = encode_url value, false, canonical
64
64
 
65
65
  result << '&' unless result.empty?
66
- result << enc_key << '='<< enc_value
66
+ result << enc_key.camelize(:lower) << '='<< enc_value
67
67
  end
68
68
  end
69
69
 
@@ -0,0 +1,42 @@
1
+ module Stormpath
2
+ module IdSite
3
+ class Error < Stormpath::Error
4
+ attr_accessor :status, :code, :message, :developer_message, :more_info
5
+
6
+ def initialize(type)
7
+ @status = errors[type][:status]
8
+ @code = errors[type][:code]
9
+ @message = errors[type][:message]
10
+ @developer_message = errors[type][:developer_message]
11
+ super(self)
12
+ end
13
+
14
+ private
15
+
16
+ def errors
17
+ {
18
+ jwt_cb_uri_incorrect: {
19
+ status: 400,
20
+ code: 400,
21
+ message: "The specified callback URI (cb_uri) is not valid",
22
+ developer_message: "The specified callback URI (cb_uri) is not valid. Make "\
23
+ "sure the callback URI specified in your ID Site configuration matches the value specified."
24
+ },
25
+ jwt_expired: {
26
+ status: 400,
27
+ code: 10011,
28
+ message: "Token is invalid",
29
+ developer_message: "Token is no longer valid because it has expired"
30
+ },
31
+ jwt_invalid: {
32
+ status: 400,
33
+ code: 10012,
34
+ message: "Token is invalid",
35
+ developer_message: "Token is invalid because the issued at time (iat) is after the current time"
36
+ }
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -1,16 +1,21 @@
1
1
  module Stormpath
2
2
  module IdSite
3
3
  class IdSiteResult
4
- attr_accessor :account_href, :state, :status, :is_new_account
4
+ attr_accessor :jwt_response, :account_href, :state, :status, :is_new_account
5
5
 
6
6
  alias_method :new_account?, :is_new_account
7
7
 
8
8
  def initialize(jwt_response)
9
+ @jwt_response = jwt_response
9
10
  @account_href = jwt_response["sub"]
10
11
  @status = jwt_response["status"]
11
12
  @state = jwt_response["state"]
12
13
  @is_new_account = jwt_response["isNewSub"]
13
14
  end
15
+
16
+ def jwt_invalid?(api_key_id)
17
+ @jwt_response['aud'] != api_key_id
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -0,0 +1,26 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class Authenticator
4
+ include Stormpath::Util::Assert
5
+
6
+ def initialize(data_store)
7
+ @data_store = data_store
8
+ end
9
+
10
+ def authenticate parent_href, request
11
+ assert_not_nil parent_href, "parent_href must be specified"
12
+
13
+ if request.grant_type == 'password'
14
+ attempt = @data_store.instantiate PasswordGrant
15
+ elsif request.grant_type == 'refresh_token'
16
+ attempt = @data_store.instantiate RefreshToken
17
+ end
18
+
19
+ attempt.set_options(request)
20
+
21
+ href = parent_href + '/oauth/token'
22
+ @data_store.create href, attempt, Stormpath::Resource::AccessToken
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class PasswordGrant < Stormpath::Resource::Base
4
+ prop_accessor :grant_type, :username, :password
5
+
6
+ def set_options(request)
7
+ set_property :username, request.username
8
+ set_property :password, request.password
9
+ set_property :grant_type, request.grant_type
10
+ end
11
+
12
+ def form_data?
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class PasswordGrantRequest
4
+ attr_accessor :grant_type, :username, :password
5
+
6
+ def initialize(username, password)
7
+ @username = username
8
+ @password = password
9
+ @grant_type = "password"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class RefreshGrantRequest
4
+ attr_accessor :grant_type, :refresh_token
5
+
6
+ def initialize(refresh_token)
7
+ @refresh_token = refresh_token
8
+ @grant_type = "refresh_token"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class RefreshToken < Stormpath::Resource::Base
4
+ prop_accessor :grant_type, :refresh_token
5
+
6
+ def set_options(request)
7
+ set_property :refresh_token, request.refresh_token
8
+ set_property :grant_type, request.grant_type
9
+ end
10
+
11
+ def form_data?
12
+ true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class VerifyAccessToken
4
+ def initialize(application)
5
+ @href = application.href
6
+ @data_store = application.client.data_store
7
+ end
8
+
9
+ def verify authorization_token
10
+ href = @href + '/authTokens/' + authorization_token
11
+ @data_store.get_resource href, VerifyToken
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Stormpath
2
+ module Oauth
3
+ class VerifyToken < Stormpath::Resource::Base
4
+ prop_reader :href, :account, :application, :jwt, :tenant, :expanded_jwt
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class Stormpath::Resource::AccessToken < Stormpath::Resource::Instance
2
+ prop_reader :access_token, :refresh_token, :token_type, :expires_in,
3
+ :stormpath_access_token_href
4
+
5
+ alias_method :href, :stormpath_access_token_href
6
+
7
+ def delete
8
+ unless href.respond_to?(:empty) and href.empty?
9
+ data_store.delete self
10
+ end
11
+ end
12
+ end
@@ -29,6 +29,7 @@ class Stormpath::Resource::Account < Stormpath::Resource::Instance
29
29
 
30
30
  has_many :groups
31
31
  has_many :group_memberships
32
+ has_many :applications
32
33
 
33
34
  has_one :custom_data
34
35
 
@@ -28,10 +28,14 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
28
28
  has_many :password_reset_tokens, can: [:get, :create]
29
29
  has_many :account_store_mappings, can: [:get, :create]
30
30
  has_many :groups, can: [:get, :create]
31
+ has_many :verification_emails, can: :create
31
32
 
32
33
  has_one :default_account_store_mapping, class_name: :accountStoreMapping
33
34
  has_one :default_group_store_mapping, class_name: :accountStoreMapping
34
35
  has_one :custom_data
36
+ has_one :o_auth_policy, class_name: :oauthPolicy
37
+
38
+ alias_method :oauth_policy, :o_auth_policy
35
39
 
36
40
  def self.load composite_url
37
41
  begin
@@ -54,6 +58,10 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
54
58
  base = client.data_store.base_url.sub("v" + Stormpath::DataStore::DEFAULT_API_VERSION.to_s, "sso")
55
59
  base += '/logout' if options[:logout]
56
60
 
61
+ if options[:callback_uri].empty?
62
+ raise Stormpath::IdSite::Error.new(:jwt_cb_uri_incorrect)
63
+ end
64
+
57
65
  token = JWT.encode({
58
66
  'iat' => Time.now.to_i,
59
67
  'jti' => UUID.method(:random_create).call.to_s,
@@ -74,11 +82,21 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
74
82
  params = CGI::parse(uri.query)
75
83
  token = params["jwtResponse"].first
76
84
 
77
- jwt_response, _header = JWT.decode(token, client.data_store.api_key.secret)
85
+ begin
86
+ jwt_response, _header = JWT.decode(token, client.data_store.api_key.secret)
87
+ rescue JWT::ExpiredSignature => error
88
+ # JWT raises error if the signature expired, we need to capture this and
89
+ # rerase IdSite::Error
90
+ raise Stormpath::IdSite::Error.new(:jwt_expired)
91
+ end
78
92
 
79
- raise Stormpath::Error.new if jwt_response["aud"] != client.data_store.api_key.id
93
+ id_site_result = Stormpath::IdSite::IdSiteResult.new(jwt_response)
80
94
 
81
- Stormpath::IdSite::IdSiteResult.new(jwt_response)
95
+ if id_site_result.jwt_invalid?(api_key_id)
96
+ raise Stormpath::IdSite::Error.new(:jwt_invalid)
97
+ end
98
+
99
+ id_site_result
82
100
  end
83
101
 
84
102
  def send_password_reset_email email
@@ -98,10 +116,17 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
98
116
  Stormpath::Provider::AccountResolver.new(data_store).resolve_provider_account(href, request)
99
117
  end
100
118
 
119
+ def authenticate_oauth(request)
120
+ Stormpath::Oauth::Authenticator.new(data_store).authenticate(href, request)
121
+ end
122
+
101
123
  private
102
124
 
103
- def create_password_reset_token email
104
- password_reset_tokens.create email: email
105
- end
125
+ def api_key_id
126
+ client.data_store.api_key.id
127
+ end
106
128
 
129
+ def create_password_reset_token email
130
+ password_reset_tokens.create email: email
131
+ end
107
132
  end
@@ -0,0 +1,5 @@
1
+ class Stormpath::Resource::OauthPolicy < Stormpath::Resource::Instance
2
+ prop_accessor :access_token_ttl, :refresh_token_ttl
3
+
4
+ belongs_to :application
5
+ end
@@ -0,0 +1,12 @@
1
+ class Stormpath::Resource::Organization < Stormpath::Resource::Instance
2
+ include Stormpath::Resource::CustomDataStorage
3
+
4
+ prop_accessor :name, :description, :name_key, :status, :account_store_mappings,
5
+ :default_account_store_mapping, :default_group_store_mapping
6
+
7
+ has_many :groups
8
+ has_many :accounts
9
+ belongs_to :tenant
10
+
11
+ has_one :custom_data
12
+ end
@@ -0,0 +1,6 @@
1
+ class Stormpath::Resource::OrganizationAccountStoreMapping < Stormpath::Resource::Instance
2
+ prop_accessor :is_default_account_store, :is_default_group_store, :list_index
3
+
4
+ belongs_to :organization
5
+ belongs_to :account_store
6
+ end
@@ -0,0 +1,5 @@
1
+ class Stormpath::Resource::VerificationEmail < Stormpath::Resource::Instance
2
+ prop_accessor :login, :account_store
3
+
4
+ belongs_to :application
5
+ end
@@ -14,6 +14,6 @@
14
14
  # limitations under the License.
15
15
  #
16
16
  module Stormpath
17
- VERSION = '1.0.0.beta.8'
18
- VERSION_DATE = '2015-07-28'
17
+ VERSION = '1.0.0.beta.9'
18
+ VERSION_DATE = '2015-12-02'
19
19
  end
data/lib/stormpath-sdk.rb CHANGED
@@ -47,6 +47,11 @@ module Stormpath
47
47
  autoload :GroupMembership, 'stormpath-sdk/resource/group_membership'
48
48
  autoload :AccountMembership, 'stormpath-sdk/resource/account_membership'
49
49
  autoload :PasswordResetToken, 'stormpath-sdk/resource/password_reset_token'
50
+ autoload :VerificationEmail, 'stormpath-sdk/resource/verification_email'
51
+ autoload :OauthPolicy, 'stormpath-sdk/resource/oauth_policy'
52
+ autoload :AccessToken, 'stormpath-sdk/resource/access_token'
53
+ autoload :Organization, 'stormpath-sdk/resource/organization'
54
+ autoload :OrganizationAccountStoreMapping, 'stormpath-sdk/resource/organization_account_store_mapping'
50
55
  end
51
56
 
52
57
  module Cache
@@ -94,5 +99,16 @@ module Stormpath
94
99
 
95
100
  module IdSite
96
101
  autoload :IdSiteResult, 'stormpath-sdk/id_site/id_site_result'
102
+ autoload :Error, 'stormpath-sdk/id_site/error'
97
103
  end
98
- end
104
+
105
+ module Oauth
106
+ autoload :Authenticator, "stormpath-sdk/oauth/authenticator"
107
+ autoload :PasswordGrant, "stormpath-sdk/oauth/password_grant"
108
+ autoload :RefreshToken, "stormpath-sdk/oauth/refresh_token"
109
+ autoload :PasswordGrantRequest, "stormpath-sdk/oauth/password_grant_request"
110
+ autoload :RefreshGrantRequest, "stormpath-sdk/oauth/refresh_grant_request"
111
+ autoload :VerifyAccessToken, "stormpath-sdk/oauth/verify_access_token"
112
+ autoload :VerifyToken, "stormpath-sdk/oauth/verify_token"
113
+ end
114
+ end
data/spec/client_spec.rb CHANGED
@@ -628,6 +628,35 @@ properties
628
628
  end
629
629
  end
630
630
 
631
+ describe "#organization_account_store_mappings" do
632
+ let(:organization) do
633
+ test_api_client.organizations.create name: 'test_organization',
634
+ name_key: "testorganization"
635
+ end
636
+
637
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
638
+
639
+ let(:organization_account_store_mappings) do
640
+ test_api_client.organization_account_store_mappings.create({
641
+ account_store: { href: directory.href },
642
+ organization: { href: organization.href }
643
+ })
644
+ end
645
+
646
+ after do
647
+ organization.delete if organization
648
+ directory.delete if directory
649
+ end
650
+
651
+ it "returns the mapping" do
652
+ expect(organization_account_store_mappings.is_default_account_store).to eq(false)
653
+ expect(organization_account_store_mappings.is_default_group_store).to eq(false)
654
+ expect(organization_account_store_mappings.organization).to eq(organization)
655
+ expect(organization_account_store_mappings.list_index).to eq(0)
656
+ expect(organization_account_store_mappings.account_store).to be_kind_of(Stormpath::Resource::Directory)
657
+ end
658
+ end
659
+
631
660
  describe '#accounts.verify_account_email' do
632
661
  context 'given a verfication token of an account' do
633
662
  let(:directory) { test_directory_with_verification }
@@ -39,12 +39,20 @@ describe Stormpath::Resource::Account, :vcr do
39
39
  expect(account.email_verification_token).to be_nil
40
40
  expect(account.groups).to be_a Stormpath::Resource::Collection
41
41
  expect(account.group_memberships).to be_a Stormpath::Resource::Collection
42
+ expect(account.applications).to be_a Stormpath::Resource::Collection
42
43
  end
43
44
  end
44
45
 
45
46
  describe 'account_associations' do
47
+ let(:app) { test_api_client.applications.create name: random_application_name, description: 'Dummy desc.' }
48
+ let(:application) { test_api_client.applications.get app.href }
46
49
  let(:directory) { test_api_client.directories.create name: random_directory_name }
47
50
 
51
+ before do
52
+ test_api_client.account_store_mappings.create({ application: app, account_store: directory,
53
+ list_index: 1, is_default_account_store: true, is_default_group_store: true })
54
+ end
55
+
48
56
  let(:account) do
49
57
  directory.accounts.create email: 'test@example.com',
50
58
  givenName: 'Ruby SDK',
@@ -57,12 +65,17 @@ describe Stormpath::Resource::Account, :vcr do
57
65
  expect(account.directory).to eq(directory)
58
66
  end
59
67
 
68
+ it 'should have many applications' do
69
+ expect(account.applications.count).to eq(1)
70
+ end
71
+
60
72
  it 'should belong_to tenant' do
61
73
  expect(account.tenant).to be
62
74
  expect(account.tenant).to eq(account.directory.tenant)
63
75
  end
64
76
 
65
77
  after do
78
+ application.delete if application
66
79
  account.delete if account
67
80
  directory.delete if directory
68
81
  end
@@ -5,6 +5,7 @@ describe Stormpath::Resource::Application, :vcr do
5
5
  let(:app) { test_api_client.applications.create name: random_application_name, description: 'Dummy desc.' }
6
6
  let(:application) { test_api_client.applications.get app.href }
7
7
  let(:directory) { test_api_client.directories.create name: random_directory_name }
8
+ let(:directory_with_verification) { test_directory_with_verification }
8
9
 
9
10
  before do
10
11
  test_api_client.account_store_mappings.create({ application: app, account_store: directory,
@@ -34,6 +35,7 @@ describe Stormpath::Resource::Application, :vcr do
34
35
  expect(application.groups).to be_a Stormpath::Resource::Collection
35
36
  expect(application.accounts).to be_a Stormpath::Resource::Collection
36
37
  expect(application.password_reset_tokens).to be_a Stormpath::Resource::Collection
38
+ expect(application.verification_emails).to be_a Stormpath::Resource::Collection
37
39
  expect(application.account_store_mappings).to be_a Stormpath::Resource::Collection
38
40
  end
39
41
 
@@ -236,6 +238,125 @@ describe Stormpath::Resource::Application, :vcr do
236
238
  end
237
239
  end
238
240
 
241
+ describe '#verification_emails' do
242
+ let(:directory_with_verification) { test_directory_with_verification }
243
+
244
+ before do
245
+ test_api_client.account_store_mappings.create({ application: app, account_store: directory_with_verification,
246
+ list_index: 1, is_default_account_store: false, is_default_group_store: false })
247
+ end
248
+
249
+ let(:account) do
250
+ directory_with_verification.accounts.create({
251
+ email: random_email,
252
+ given_name: 'Ruby SDK',
253
+ password: 'P@$$w0rd',
254
+ surname: 'SDK',
255
+ username: random_user_name
256
+ })
257
+ end
258
+
259
+ let(:verification_emails) do
260
+ application.verification_emails.create(login: account.email)
261
+ end
262
+
263
+ after do
264
+ account.delete if account
265
+ end
266
+
267
+ it 'returns verification email' do
268
+ expect(verification_emails).to be_kind_of Stormpath::Resource::VerificationEmail
269
+ end
270
+ end
271
+
272
+ describe 'create_login_attempt' do
273
+ let(:account) do
274
+ directory.accounts.create({
275
+ email: random_email,
276
+ given_name: 'Ruby SDK',
277
+ password: 'P@$$w0rd',
278
+ surname: 'SDK',
279
+ username: random_user_name
280
+ })
281
+ end
282
+
283
+ context 'valid credentials' do
284
+ let(:username_password_request) do
285
+ Stormpath::Authentication::UsernamePasswordRequest.new(
286
+ account.email,
287
+ "P@$$w0rd"
288
+ )
289
+ end
290
+
291
+ let(:auth_request) { application.authenticate_account(username_password_request) }
292
+
293
+ it 'returns login attempt response' do
294
+ expect(auth_request).to be_kind_of Stormpath::Authentication::AuthenticationResult
295
+ end
296
+
297
+ it 'containes account data' do
298
+ expect(auth_request.account.href).to eq(account.href)
299
+ end
300
+ end
301
+
302
+ context 'with organization as account store option' do
303
+ def create_organization_account_store_mapping(organization, account_store)
304
+ test_api_client.organization_account_store_mappings.create({
305
+ account_store: { href: account_store.href },
306
+ organization: { href: organization.href }
307
+ })
308
+ end
309
+
310
+ let(:organization) do
311
+ test_api_client.organizations.create name: 'test_organization',
312
+ name_key: "testorganization"
313
+ end
314
+
315
+ let(:username_password_request) do
316
+ Stormpath::Authentication::UsernamePasswordRequest.new(
317
+ account.email,
318
+ "P@$$w0rd",
319
+ account_store: organization.name_key
320
+ )
321
+ end
322
+
323
+ let(:auth_request) { application.authenticate_account(username_password_request) }
324
+
325
+ before do
326
+ create_organization_account_store_mapping(organization, directory)
327
+ end
328
+
329
+ after do
330
+ organization.delete if organization
331
+ end
332
+
333
+ it 'returns login attempt response' do
334
+ expect(auth_request).to be_kind_of Stormpath::Authentication::AuthenticationResult
335
+ end
336
+
337
+ it 'containes account data' do
338
+ expect(auth_request.account.href).to eq(account.href)
339
+ end
340
+ end
341
+
342
+ context 'with invalid credentials' do
343
+ let(:username_password_request) do
344
+ Stormpath::Authentication::UsernamePasswordRequest.new(
345
+ account.email,
346
+ "invalid"
347
+ )
348
+ end
349
+
350
+ let(:auth_request) { application.authenticate_account(username_password_request) }
351
+
352
+ it 'returns stormpath error' do
353
+ expect {
354
+ auth_request
355
+ }.to raise_error(Stormpath::Error)
356
+ end
357
+ end
358
+ end
359
+
239
360
  describe '#verify_password_reset_token' do
240
361
  let(:account) do
241
362
  directory.accounts.create({
@@ -338,6 +459,25 @@ describe Stormpath::Resource::Application, :vcr do
338
459
  it 'shoud create a request to /sso/logout' do
339
460
  end
340
461
  end
462
+
463
+ context 'without providing cb_uri' do
464
+ let(:create_id_site_url_result) do
465
+ options = { callback_uri: '' }
466
+ application.create_id_site_url options
467
+ end
468
+
469
+ it 'should raise Stormpath Error with correct id_site error data' do
470
+ begin
471
+ create_id_site_url_result
472
+ rescue Stormpath::Error => error
473
+ expect(error.status).to eq(400)
474
+ expect(error.code).to eq(400)
475
+ expect(error.message).to eq("The specified callback URI (cb_uri) is not valid")
476
+ expect(error.developer_message).to eq("The specified callback URI (cb_uri) is not valid. Make sure the "\
477
+ "callback URI specified in your ID Site configuration matches the value specified.")
478
+ end
479
+ end
480
+ end
341
481
  end
342
482
 
343
483
  describe '#handle_id_site_callback' do
@@ -399,10 +539,21 @@ describe Stormpath::Resource::Application, :vcr do
399
539
  }, test_api_key_secret, 'HS256')
400
540
  }
401
541
 
542
+ it 'should raise Stormpath Error with correct data' do
543
+ begin
544
+ application.handle_id_site_callback(callback_uri_base + jwt_token)
545
+ rescue Stormpath::Error => error
546
+ expect(error.status).to eq(400)
547
+ expect(error.code).to eq(10011)
548
+ expect(error.message).to eq("Token is invalid")
549
+ expect(error.developer_message).to eq("Token is no longer valid because it has expired")
550
+ end
551
+ end
552
+
402
553
  it 'should raise expiration error' do
403
554
  expect {
404
555
  application.handle_id_site_callback(callback_uri_base + jwt_token)
405
- }.to raise_error(JWT::DecodeError)
556
+ }.to raise_error(Stormpath::Error)
406
557
  end
407
558
  end
408
559
 
@@ -423,6 +574,18 @@ describe Stormpath::Resource::Application, :vcr do
423
574
  application.handle_id_site_callback(callback_uri_base + jwt_token)
424
575
  }.to raise_error(Stormpath::Error)
425
576
  end
577
+
578
+ it 'should raise Stormpath Error with correct id_site error data' do
579
+ begin
580
+ application.handle_id_site_callback(callback_uri_base + jwt_token)
581
+ rescue Stormpath::Error => error
582
+ expect(error.status).to eq(400)
583
+ expect(error.code).to eq(10012)
584
+ expect(error.message).to eq("Token is invalid")
585
+ expect(error.developer_message).to eq("Token is invalid because the issued at time (iat) "\
586
+ "is after the current time")
587
+ end
588
+ end
426
589
  end
427
590
 
428
591
  context 'with an invalid exp value' do
@@ -438,10 +601,10 @@ describe Stormpath::Resource::Application, :vcr do
438
601
  }, test_api_key_secret, 'HS256')
439
602
  }
440
603
 
441
- it 'should error with the expiration error' do
604
+ it 'should error with the stormpath error' do
442
605
  expect {
443
606
  application.handle_id_site_callback(callback_uri_base + jwt_token)
444
- }.to raise_error(JWT::DecodeError)
607
+ }.to raise_error(Stormpath::Error)
445
608
  end
446
609
  end
447
610
 
@@ -464,4 +627,81 @@ describe Stormpath::Resource::Application, :vcr do
464
627
  end
465
628
  end
466
629
  end
630
+
631
+ describe '#authenticate_oauth' do
632
+ let(:account_data) { build_account }
633
+ let(:password_grant_request) { Stormpath::Oauth::PasswordGrantRequest.new account_data[:email], account_data[:password] }
634
+ let(:aquire_token) { application.authenticate_oauth(password_grant_request) }
635
+
636
+ before do
637
+ application.accounts.create account_data
638
+ end
639
+
640
+ context 'generate access token' do
641
+ let(:password_grant_request) { Stormpath::Oauth::PasswordGrantRequest.new account_data[:email], account_data[:password] }
642
+ let(:authenticate_oauth) { application.authenticate_oauth(password_grant_request) }
643
+
644
+ it 'should return access token response' do
645
+ expect(authenticate_oauth).to be_kind_of(Stormpath::Resource::AccessToken)
646
+ end
647
+
648
+ it 'response should contain token data' do
649
+ expect(authenticate_oauth.access_token).not_to be_empty
650
+ expect(authenticate_oauth.refresh_token).not_to be_empty
651
+ expect(authenticate_oauth.token_type).not_to be_empty
652
+ expect(authenticate_oauth.expires_in).not_to be_nil
653
+ expect(authenticate_oauth.stormpath_access_token_href).not_to be_empty
654
+ end
655
+ end
656
+
657
+ context 'refresh token' do
658
+ let(:refresh_grant_request) { Stormpath::Oauth::RefreshGrantRequest.new aquire_token.refresh_token }
659
+ let(:authenticate_oauth) { application.authenticate_oauth(refresh_grant_request) }
660
+
661
+ it 'should return access token response with refreshed token' do
662
+ expect(authenticate_oauth).to be_kind_of(Stormpath::Resource::AccessToken)
663
+ end
664
+
665
+ it 'refreshed token is not the same as previous one' do
666
+ expect(authenticate_oauth.access_token).not_to be_equal(aquire_token.access_token)
667
+ end
668
+
669
+ it 'returens success with data' do
670
+ expect(authenticate_oauth.access_token).not_to be_empty
671
+ expect(authenticate_oauth.refresh_token).not_to be_empty
672
+ expect(authenticate_oauth.token_type).not_to be_empty
673
+ expect(authenticate_oauth.expires_in).not_to be_nil
674
+ expect(authenticate_oauth.stormpath_access_token_href).not_to be_empty
675
+ end
676
+ end
677
+
678
+ context 'validate access token' do
679
+ let(:access_token) { aquire_token.access_token }
680
+ let(:authenticate_oauth) { Stormpath::Oauth::VerifyAccessToken.new(application).verify(access_token) }
681
+
682
+ it 'should return authentication result response' do
683
+ expect(authenticate_oauth).to be_kind_of(Stormpath::Oauth::VerifyToken)
684
+ end
685
+
686
+ it 'returens success on valid token' do
687
+ expect(authenticate_oauth.href).not_to be_empty
688
+ expect(authenticate_oauth.account).not_to be_empty
689
+ expect(authenticate_oauth.application).not_to be_empty
690
+ expect(authenticate_oauth.jwt).not_to be_empty
691
+ expect(authenticate_oauth.tenant).not_to be_empty
692
+ expect(authenticate_oauth.expanded_jwt).not_to be_empty
693
+ end
694
+ end
695
+
696
+ context 'delete token' do
697
+ it 'after token was deleted user can authenticate with the same token' do
698
+ access_token = aquire_token.access_token
699
+ aquire_token.delete
700
+
701
+ expect {
702
+ Stormpath::Oauth::VerifyAccessToken.new(application).verify(access_token)
703
+ }.to raise_error(Stormpath::Error)
704
+ end
705
+ end
706
+ end
467
707
  end
@@ -3,10 +3,19 @@ require 'spec_helper'
3
3
  describe Stormpath::Resource::Directory, :vcr do
4
4
 
5
5
  describe "instances should respond to attribute property methods" do
6
+ let(:app) { test_api_client.applications.create name: random_application_name, description: 'Dummy desc.' }
7
+ let(:application) { test_api_client.applications.get app.href }
6
8
  let(:directory) { test_api_client.directories.create name: random_directory_name, description: 'description_for_some_test_directory' }
9
+ let(:directory_with_verification) { test_directory_with_verification }
10
+
11
+ before do
12
+ test_api_client.account_store_mappings.create({ application: app, account_store: directory_with_verification,
13
+ list_index: 1, is_default_account_store: false, is_default_group_store: false })
14
+ end
7
15
 
8
16
  after do
9
17
  directory.delete if directory
18
+ application.delete if application
10
19
  end
11
20
 
12
21
  it do
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stormpath::Resource::Organization, :vcr do
4
+
5
+ let(:organization) do
6
+ test_api_client.organizations.create name: 'test_organization',
7
+ name_key: "testorganization"
8
+ end
9
+
10
+ after do
11
+ organization.delete if organization
12
+ end
13
+
14
+ def create_organization_account_store_mapping(organization, account_store)
15
+ test_api_client.organization_account_store_mappings.create({
16
+ account_store: { href: account_store.href },
17
+ organization: { href: organization.href }
18
+ })
19
+ end
20
+
21
+ describe 'get resource' do
22
+ let(:fetched_organization) { test_api_client.organizations.get organization.href }
23
+
24
+ it 'returns the organization resource with correct attribute properties' do
25
+ expect(fetched_organization).to be_kind_of(Stormpath::Resource::Organization)
26
+ expect(fetched_organization.name).to eq(organization.name)
27
+ expect(fetched_organization.description).to eq(organization.description)
28
+ expect(fetched_organization.name_key).to eq(organization.name_key)
29
+ expect(fetched_organization.status).to eq(organization.status)
30
+ expect(fetched_organization.account_store_mappings).to eq(organization.account_store_mappings)
31
+ expect(fetched_organization.default_account_store_mapping).to eq(organization.default_account_store_mapping)
32
+ expect(fetched_organization.default_group_store_mapping).to eq(organization.default_group_store_mapping)
33
+ end
34
+
35
+ it 'returns custom_data' do
36
+ expect(organization.custom_data).to be_a Stormpath::Resource::CustomData
37
+ end
38
+ end
39
+
40
+ describe 'create' do
41
+ context 'invalid data' do
42
+ it 'should raise Stormpath::Error' do
43
+ expect do
44
+ test_api_client.organizations.create name: 'test_organization',
45
+ name_key: "test_org"
46
+ end.to raise_error(Stormpath::Error)
47
+ end
48
+ end
49
+ end
50
+
51
+ describe 'associations' do
52
+ context 'groups' do
53
+
54
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
55
+
56
+ let(:group) { directory.groups.create name: "test_group" }
57
+
58
+ before do
59
+ create_organization_account_store_mapping(organization, group)
60
+ end
61
+
62
+ after do
63
+ organization.delete if organization
64
+ directory.delete if directory
65
+ end
66
+
67
+ it 'returns a collection of groups' do
68
+ expect(organization.groups).to be_kind_of(Stormpath::Resource::Collection)
69
+ expect(organization.groups).to include(group)
70
+ end
71
+ end
72
+
73
+ context 'accounts' do
74
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
75
+
76
+ let(:account) { directory.accounts.create({ email: 'rubysdk@example.com', given_name: 'Ruby SDK', password: 'P@$$w0rd',surname: 'SDK' }) }
77
+
78
+ before do
79
+ create_organization_account_store_mapping(organization, directory)
80
+ end
81
+
82
+ after do
83
+ organization.delete if organization
84
+ directory.delete if directory
85
+ end
86
+
87
+ it 'returns a collection of groups' do
88
+ expect(organization.accounts).to be_kind_of(Stormpath::Resource::Collection)
89
+ expect(organization.accounts).to include(account)
90
+ end
91
+ end
92
+
93
+ context 'tenant' do
94
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
95
+
96
+ before do
97
+ create_organization_account_store_mapping(organization, directory)
98
+ end
99
+
100
+ after do
101
+ organization.delete if organization
102
+ directory.delete if directory
103
+ end
104
+
105
+ it 'returns tenant' do
106
+ expect(organization.tenant).to eq(directory.tenant)
107
+ end
108
+ end
109
+ end
110
+
111
+ describe 'delete' do
112
+ let(:href) { organization.href }
113
+
114
+ before do
115
+ organization.delete
116
+ end
117
+
118
+ it 'removes the organization' do
119
+ expect do
120
+ test_api_client.organizations.get href
121
+ end.to raise_error(Stormpath::Error)
122
+ end
123
+ end
124
+
125
+ describe 'update' do
126
+ before do
127
+ organization.name_key = "changed-test-organization"
128
+ organization.save
129
+ end
130
+
131
+ it 'can change the data of the existing organization' do
132
+ org = test_api_client.organizations.get organization.href
133
+ expect(org.name_key).to eq("changed-test-organization")
134
+ end
135
+ end
136
+
137
+ describe 'organization account store mapping' do
138
+ context 'given an account_store is a directory' do
139
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
140
+
141
+ let(:organization_account_store_mapping) do
142
+ create_organization_account_store_mapping(organization, directory)
143
+ end
144
+
145
+ let(:reloaded_mapping) do
146
+ test_api_client.account_store_mappings.get organization_account_store_mapping.href
147
+ end
148
+
149
+ after do
150
+ organization.delete if organization
151
+ directory.delete if directory
152
+ end
153
+
154
+ it 'should return a directory' do
155
+ expect(reloaded_mapping.account_store.class).to eq(Stormpath::Resource::Directory)
156
+ expect(reloaded_mapping.account_store).to eq(directory)
157
+ end
158
+ end
159
+
160
+ context 'given an account_store is a group' do
161
+ let(:directory) { test_api_client.directories.create name: random_directory_name }
162
+
163
+ let(:group) { directory.groups.create name: "test_group" }
164
+
165
+ let(:organization_account_store_mapping) do
166
+ create_organization_account_store_mapping(organization, group)
167
+ end
168
+
169
+ let(:reloaded_mapping) do
170
+ test_api_client.account_store_mappings.get organization_account_store_mapping.href
171
+ end
172
+
173
+ after do
174
+ organization.delete if organization
175
+ group.delete if group
176
+ directory.delete if directory
177
+ end
178
+
179
+ it 'should return group' do
180
+ expect(reloaded_mapping.account_store.class).to eq(Stormpath::Resource::Group)
181
+ expect(reloaded_mapping.account_store).to eq(group)
182
+ end
183
+ end
184
+ end
185
+ end
@@ -74,7 +74,7 @@ shared_examples_for 'custom_data_storage' do
74
74
  RESERVED_FIELDS.each do |reserved_field|
75
75
  it "set reserved data #{reserved_field} should raise error" do
76
76
  custom_data_storage.custom_data[reserved_field] = 12
77
- expect{ custom_data_storage.custom_data.save }.to raise_error
77
+ expect{ custom_data_storage.custom_data.save }.to raise_error Stormpath::Error
78
78
  end
79
79
  end
80
80
 
@@ -388,4 +388,4 @@ shared_examples_for 'custom_data_storage' do
388
388
  def deleted_properties
389
389
  custom_data_storage.custom_data.instance_variable_get("@deleted_properties")
390
390
  end
391
- end
391
+ end
@@ -34,4 +34,4 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency 'redis', '~> 3.0.4'
35
35
 
36
36
  s.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'stormpath-sdk', '--main']
37
- end
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stormpath-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta.8
4
+ version: 1.0.0.beta.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stormpath, Inc
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-28 00:00:00.000000000 Z
12
+ date: 2015-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -283,7 +283,15 @@ files:
283
283
  - lib/stormpath-sdk/http/request.rb
284
284
  - lib/stormpath-sdk/http/response.rb
285
285
  - lib/stormpath-sdk/http/utils.rb
286
+ - lib/stormpath-sdk/id_site/error.rb
286
287
  - lib/stormpath-sdk/id_site/id_site_result.rb
288
+ - lib/stormpath-sdk/oauth/authenticator.rb
289
+ - lib/stormpath-sdk/oauth/password_grant.rb
290
+ - lib/stormpath-sdk/oauth/password_grant_request.rb
291
+ - lib/stormpath-sdk/oauth/refresh_grant_request.rb
292
+ - lib/stormpath-sdk/oauth/refresh_token.rb
293
+ - lib/stormpath-sdk/oauth/verify_access_token.rb
294
+ - lib/stormpath-sdk/oauth/verify_token.rb
287
295
  - lib/stormpath-sdk/provider/account_access.rb
288
296
  - lib/stormpath-sdk/provider/account_request.rb
289
297
  - lib/stormpath-sdk/provider/account_resolver.rb
@@ -296,6 +304,7 @@ files:
296
304
  - lib/stormpath-sdk/provider/provider_data.rb
297
305
  - lib/stormpath-sdk/provider/stormpath/stormpath_provider.rb
298
306
  - lib/stormpath-sdk/provider/stormpath/stormpath_provider_data.rb
307
+ - lib/stormpath-sdk/resource/access_token.rb
299
308
  - lib/stormpath-sdk/resource/account.rb
300
309
  - lib/stormpath-sdk/resource/account_membership.rb
301
310
  - lib/stormpath-sdk/resource/account_status.rb
@@ -315,10 +324,14 @@ files:
315
324
  - lib/stormpath-sdk/resource/group.rb
316
325
  - lib/stormpath-sdk/resource/group_membership.rb
317
326
  - lib/stormpath-sdk/resource/instance.rb
327
+ - lib/stormpath-sdk/resource/oauth_policy.rb
328
+ - lib/stormpath-sdk/resource/organization.rb
329
+ - lib/stormpath-sdk/resource/organization_account_store_mapping.rb
318
330
  - lib/stormpath-sdk/resource/password_reset_token.rb
319
331
  - lib/stormpath-sdk/resource/status.rb
320
332
  - lib/stormpath-sdk/resource/tenant.rb
321
333
  - lib/stormpath-sdk/resource/utils.rb
334
+ - lib/stormpath-sdk/resource/verification_email.rb
322
335
  - lib/stormpath-sdk/util/assert.rb
323
336
  - lib/stormpath-sdk/version.rb
324
337
  - spec/api_key_spec.rb
@@ -342,6 +355,7 @@ files:
342
355
  - spec/resource/expansion_spec.rb
343
356
  - spec/resource/group_membership_spec.rb
344
357
  - spec/resource/group_spec.rb
358
+ - spec/resource/organization_spec.rb
345
359
  - spec/resource/status_spec.rb
346
360
  - spec/resource/tenant_spec.rb
347
361
  - spec/spec_helper.rb
@@ -382,3 +396,4 @@ signing_key:
382
396
  specification_version: 4
383
397
  summary: Stormpath SDK
384
398
  test_files: []
399
+ has_rdoc: