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

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.
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: