stormpath-sdk 1.0.1 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGES.md +11 -0
- data/README.md +234 -3
- data/Rakefile +3 -1
- data/lib/stormpath-sdk.rb +4 -0
- data/lib/stormpath-sdk/auth/basic_login_attempt.rb +4 -0
- data/lib/stormpath-sdk/auth/username_password_request.rb +0 -1
- data/lib/stormpath-sdk/client.rb +1 -1
- data/lib/stormpath-sdk/data_store.rb +17 -9
- data/lib/stormpath-sdk/provider/saml/saml_mapping_rules.rb +22 -0
- data/lib/stormpath-sdk/provider/saml/saml_provider.rb +20 -0
- data/lib/stormpath-sdk/provider/saml/saml_provider_data.rb +19 -0
- data/lib/stormpath-sdk/provider/saml/saml_provider_metadata.rb +19 -0
- data/lib/stormpath-sdk/resource/application.rb +22 -7
- data/lib/stormpath-sdk/resource/directory.rb +16 -0
- data/lib/stormpath-sdk/version.rb +2 -2
- data/spec/client_spec.rb +108 -13
- data/spec/fixtures/response/create_saml_directory.json +26 -0
- data/spec/fixtures/response/create_saml_directory_mapping_rules.json +12 -0
- data/spec/fixtures/response/get_saml_directory_provider.json +16 -0
- data/spec/fixtures/response/get_saml_directory_provider_metadata.json +12 -0
- data/spec/resource/application_spec.rb +378 -33
- data/spec/resource/directory_spec.rb +168 -0
- data/spec/spec_helper.rb +14 -1
- data/stormpath-sdk.gemspec +1 -0
- metadata +25 -3
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016 Stormpath, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
class Stormpath::Provider::SamlMappingRules < Stormpath::Provider::Provider
|
17
|
+
prop_reader :href, :created_at, :modified_at, :items
|
18
|
+
|
19
|
+
def set_options(options)
|
20
|
+
set_property :href, options[:href]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016 Stormpath, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
class Stormpath::Provider::SamlProvider < Stormpath::Provider::Provider
|
17
|
+
prop_reader :provider_id, :sso_login_url, :sso_logout_url,
|
18
|
+
:encoded_x509_signing_cert, :request_signature_algorithm,
|
19
|
+
:service_provider_metadata, :attribute_statement_mapping_rules
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016 Stormpath, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
class Stormpath::Provider::SamlProviderData < Stormpath::Provider::ProviderData
|
17
|
+
prop_reader :href, :created_at, :modified_at, :provider_id, :sso_log_in_url,
|
18
|
+
:sso_lgout_url
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016 Stormpath, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
class Stormpath::Provider::SamlProviderMetadata < Stormpath::Provider::ProviderData
|
17
|
+
prop_reader :href, :created_at, :modified_at, :entity_id, :x509_signing_cert,
|
18
|
+
:assertion_consumer_service_post_endpoint
|
19
|
+
end
|
@@ -21,7 +21,7 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
|
|
21
21
|
|
22
22
|
class LoadError < Stormpath::Error; end
|
23
23
|
|
24
|
-
prop_accessor :name, :description
|
24
|
+
prop_accessor :name, :description, :authorized_callback_uris
|
25
25
|
|
26
26
|
belongs_to :tenant
|
27
27
|
|
@@ -91,8 +91,8 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
|
|
91
91
|
id_site_result
|
92
92
|
end
|
93
93
|
|
94
|
-
def send_password_reset_email
|
95
|
-
password_reset_token = create_password_reset_token
|
94
|
+
def send_password_reset_email(email, account_store: nil)
|
95
|
+
password_reset_token = create_password_reset_token(email, account_store: account_store)
|
96
96
|
password_reset_token.account
|
97
97
|
end
|
98
98
|
|
@@ -109,9 +109,9 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def authenticate_oauth(request)
|
112
|
-
Stormpath::Oauth::Authenticator.new(data_store).authenticate(href, request)
|
112
|
+
Stormpath::Oauth::Authenticator.new(data_store).authenticate(href, request)
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
private
|
116
116
|
|
117
117
|
def jwt_token_payload(options)
|
@@ -135,7 +135,22 @@ class Stormpath::Resource::Application < Stormpath::Resource::Instance
|
|
135
135
|
client.data_store.api_key.id
|
136
136
|
end
|
137
137
|
|
138
|
-
def create_password_reset_token
|
139
|
-
|
138
|
+
def create_password_reset_token(email, account_store: nil)
|
139
|
+
params = { email: email }
|
140
|
+
params[:account_store] = account_store_to_hash(account_store) if account_store
|
141
|
+
password_reset_tokens.create(params)
|
142
|
+
end
|
143
|
+
|
144
|
+
def account_store_to_hash(account_store)
|
145
|
+
case account_store
|
146
|
+
when Stormpath::Resource::Organization
|
147
|
+
{ name_key: account_store.name_key }
|
148
|
+
when Stormpath::Resource::Group, Stormpath::Resource::Directory
|
149
|
+
{ href: account_store.href }
|
150
|
+
when Hash
|
151
|
+
account_store
|
152
|
+
else
|
153
|
+
fail ArgumentError, 'Account store has to be passed either as an resource or a hash'
|
154
|
+
end
|
140
155
|
end
|
141
156
|
end
|
@@ -40,4 +40,20 @@ class Stormpath::Resource::Directory < Stormpath::Resource::Instance
|
|
40
40
|
provider = data_store.get_resource provider_href, clazz_proc
|
41
41
|
instance_variable_set "@_provider", provider
|
42
42
|
end
|
43
|
+
|
44
|
+
def provider_metadata
|
45
|
+
metadata_href = provider.service_provider_metadata["href"]
|
46
|
+
data_store.get_resource metadata_href, Stormpath::Provider::SamlProviderMetadata
|
47
|
+
end
|
48
|
+
|
49
|
+
def statement_mapping_rules
|
50
|
+
metadata_href = provider.attribute_statement_mapping_rules["href"]
|
51
|
+
data_store.get_resource metadata_href, Stormpath::Provider::SamlMappingRules
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_attribute_mappings(mappings)
|
55
|
+
mappings.set_options(href: provider.attribute_statement_mapping_rules["href"])
|
56
|
+
data_store.create mappings.href, mappings, Stormpath::Provider::SamlMappingRules
|
57
|
+
end
|
43
58
|
end
|
59
|
+
|
data/spec/client_spec.rb
CHANGED
@@ -12,17 +12,20 @@ describe Stormpath::Client, :vcr do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
let(:api_key_and_secret_properties) do
|
16
|
+
<<-properties
|
17
|
+
apiKey.id=#{test_api_key_id}
|
18
|
+
apiKey.secret=#{test_api_key_secret}
|
19
|
+
properties
|
20
|
+
end
|
21
|
+
|
15
22
|
context 'given a hash' do
|
16
23
|
context 'with an api key file location', 'that points to a remote file' do
|
17
24
|
let(:api_key_file_location) { 'http://fake.server.com/apiKey.properties' }
|
18
25
|
let(:client) { Stormpath::Client.new(api_key_file_location: api_key_file_location) }
|
19
26
|
|
20
27
|
before do
|
21
|
-
stub_request(:any, api_key_file_location).to_return(body
|
22
|
-
apiKey.id=#{test_api_key_id}
|
23
|
-
apiKey.secret=#{test_api_key_secret}
|
24
|
-
properties
|
25
|
-
)
|
28
|
+
stub_request(:any, api_key_file_location).to_return(body: api_key_and_secret_properties)
|
26
29
|
end
|
27
30
|
|
28
31
|
it_behaves_like 'a valid client'
|
@@ -224,11 +227,7 @@ properties
|
|
224
227
|
end
|
225
228
|
|
226
229
|
before do
|
227
|
-
stub_request(:any, api_key_file_location).to_return(body
|
228
|
-
apiKey.id=#{test_api_key_id}
|
229
|
-
apiKey.secret=#{test_api_key_secret}
|
230
|
-
properties
|
231
|
-
)
|
230
|
+
stub_request(:any, api_key_file_location).to_return(body: api_key_and_secret_properties)
|
232
231
|
data_store = client.instance_variable_get '@data_store'
|
233
232
|
cache_manager = data_store.cache_manager
|
234
233
|
@directories_cache = cache_manager.get_cache 'directories'
|
@@ -397,13 +396,11 @@ properties
|
|
397
396
|
expect(groups_cache_summary).to eq [2, 1, 0, 0, 2]
|
398
397
|
end
|
399
398
|
end
|
400
|
-
|
401
399
|
end
|
402
400
|
|
403
401
|
context 'search' do
|
404
|
-
|
405
402
|
let(:first_application_name) { random_application_name(1) }
|
406
|
-
let(:second_application_name
|
403
|
+
let(:second_application_name) { random_application_name(2) }
|
407
404
|
|
408
405
|
let!(:applications) do
|
409
406
|
[
|
@@ -628,6 +625,104 @@ properties
|
|
628
625
|
end
|
629
626
|
end
|
630
627
|
|
628
|
+
describe '#organization' do
|
629
|
+
context 'search' do
|
630
|
+
let(:organization_name) { random_organization_name }
|
631
|
+
|
632
|
+
let!(:organization) do
|
633
|
+
test_api_client.organizations.create(
|
634
|
+
name: organization_name,
|
635
|
+
name_key: "testorganization"
|
636
|
+
)
|
637
|
+
end
|
638
|
+
|
639
|
+
context 'by any attribute' do
|
640
|
+
let(:search_results) do
|
641
|
+
test_api_client.organizations.search(organization_name)
|
642
|
+
end
|
643
|
+
|
644
|
+
it 'returns the application' do
|
645
|
+
expect(search_results.count).to eq 1
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
context 'by an explicit attribute' do
|
650
|
+
let(:search_results) do
|
651
|
+
test_api_client.organizations.search(name: random_organization_name)
|
652
|
+
end
|
653
|
+
|
654
|
+
it 'returns the application' do
|
655
|
+
expect(search_results.count).to eq 1
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
after { organization.delete }
|
660
|
+
end
|
661
|
+
|
662
|
+
context 'given a collection' do
|
663
|
+
let(:organization) do
|
664
|
+
test_api_client.organizations.create(
|
665
|
+
name: random_organization_name,
|
666
|
+
name_key: random_name_key,
|
667
|
+
description: 'A test description'
|
668
|
+
)
|
669
|
+
end
|
670
|
+
|
671
|
+
it 'returns the collection' do
|
672
|
+
expect(test_api_client.organizations).to be_kind_of(Stormpath::Resource::Collection)
|
673
|
+
expect(test_api_client.organizations.count).to be >= 1
|
674
|
+
end
|
675
|
+
|
676
|
+
after { organization.delete }
|
677
|
+
end
|
678
|
+
|
679
|
+
context 'given a collection with a limit' do
|
680
|
+
let!(:organization_1) do
|
681
|
+
test_api_client.organizations.create name: random_organization_name(1), name_key: random_name_key(1)
|
682
|
+
end
|
683
|
+
|
684
|
+
let!(:organization_2) do
|
685
|
+
test_api_client.organizations.create name: random_organization_name(2), name_key: random_name_key(2)
|
686
|
+
end
|
687
|
+
|
688
|
+
after do
|
689
|
+
organization_1.delete
|
690
|
+
organization_2.delete
|
691
|
+
end
|
692
|
+
|
693
|
+
it 'should retrieve the number of organizations described with the limit' do
|
694
|
+
expect(test_api_client.organizations.count).to be >= 2
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
describe '.create' do
|
699
|
+
let(:organization_name) { random_organization_name }
|
700
|
+
|
701
|
+
let(:organization_attributes) do
|
702
|
+
{
|
703
|
+
name: organization_name,
|
704
|
+
name_key: random_name_key,
|
705
|
+
description: 'A test description'
|
706
|
+
}
|
707
|
+
end
|
708
|
+
|
709
|
+
let(:organization) do
|
710
|
+
test_api_client.organizations.create organization_attributes
|
711
|
+
end
|
712
|
+
|
713
|
+
it 'creates an organization' do
|
714
|
+
expect(organization).to be
|
715
|
+
expect(organization.name).to eq(organization_attributes[:name])
|
716
|
+
expect(organization.name_key).to eq(organization_attributes[:name_key])
|
717
|
+
expect(organization.description).to eq(organization_attributes[:description])
|
718
|
+
end
|
719
|
+
|
720
|
+
after do
|
721
|
+
organization.delete
|
722
|
+
end
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
631
726
|
describe "#organization_account_store_mappings" do
|
632
727
|
let(:organization) do
|
633
728
|
test_api_client.organizations.create name: 'test_organization',
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn",
|
3
|
+
"name":"test_directory_",
|
4
|
+
"description":"description_for_some_test_directory",
|
5
|
+
"status":"ENABLED",
|
6
|
+
"createdAt":"2016-02-05T11:48:28.970Z",
|
7
|
+
"modifiedAt":"2016-02-05T11:48:28.970Z",
|
8
|
+
"tenant":{"href":"https://api.stormpath.com/v1/tenants/3BoGKJZ6kwMlIqWCIYf8hr"},
|
9
|
+
"provider":{
|
10
|
+
"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/provider",
|
11
|
+
"provider_id": "saml",
|
12
|
+
"sso_login_url": "https://yourIdp.com/saml2/sso/login",
|
13
|
+
"sso_logout_url": "https://yourIdp.com/saml2/sso/logout",
|
14
|
+
"encoded_x509_signing_cert": "-----BEGIN CERTIFICATE-----\n...Certificate goes here...\n-----END CERTIFICATE-----",
|
15
|
+
"request_signature_algorithm": "RSA-SHA256"
|
16
|
+
},
|
17
|
+
"customData":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/customData"},
|
18
|
+
"passwordPolicy":{"href":"https://api.stormpath.com/v1/passwordPolicies/2uH3tJWHS4ZE5R7gcOzmGn"},
|
19
|
+
"accountCreationPolicy":{"href":"https://api.stormpath.com/v1/accountCreationPolicies/2uH3tJWHS4ZE5R7gcOzmGn"},
|
20
|
+
"accounts":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/accounts"},
|
21
|
+
"applicationMappings":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/applicationMappings"},
|
22
|
+
"applications":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/applications"},
|
23
|
+
"groups":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/groups"},
|
24
|
+
"organizations":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/organizations"},
|
25
|
+
"organizationMappings":{"href":"https://api.stormpath.com/v1/directories/2uH3tJWHS4ZE5R7gcOzmGn/organizationMappings"}
|
26
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"href": "https://api.stormpath.com/v1/attributeStatementMappingRules/5Gd35dLZfFI1DB29xA6ZMe",
|
3
|
+
"createdAt": "2016-01-27T09:52:28.564Z",
|
4
|
+
"modifiedAt": "2016-02-29T12:58:50.496Z",
|
5
|
+
"items": [
|
6
|
+
{
|
7
|
+
"name": "uid4",
|
8
|
+
"name_format": "nil",
|
9
|
+
"account_attributes": ["username"]
|
10
|
+
}
|
11
|
+
]
|
12
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"href": "https://api.stormpath.com/v1/directories/5GbnGg4HIqoFdlRjHndYQC/provider",
|
3
|
+
"createdAt": "2016-01-27T09:52:32.850Z",
|
4
|
+
"modifiedAt": "2016-01-27T09:52:32.850Z",
|
5
|
+
"providerId": "saml",
|
6
|
+
"ssoLoginUrl": "https://yourIdp.com/saml2/sso/login",
|
7
|
+
"ssoLogoutUrl": "https://yourIdp.com/saml2/sso/logout",
|
8
|
+
"encoded_x509_signing_cert": "-----BEGIN CERTIFICATE-----\n...Certificate goes here...\n-----END CERTIFICATE-----",
|
9
|
+
"requestSignatureAlgorithm": "RSA-SHA256",
|
10
|
+
"attributeStatementMappingRules": {
|
11
|
+
"href": "https://api.stormpath.com/v1/attributeStatementMappingRules/5Gd35dLZfFI1DB29xA6ZMe"
|
12
|
+
},
|
13
|
+
"serviceProviderMetadata": {
|
14
|
+
"href": "https://api.stormpath.com/v1/samlServiceProviderMetadatas/5LRVP0EMfrpHYijuqgCUAq"
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"href": "https://api.stormpath.com/v1/samlServiceProviderMetadatas/5LRVP0EMfrpHYijuqgCUAq",
|
3
|
+
"createdAt": "2016-01-27T09:52:32.844Z",
|
4
|
+
"modifiedAt": "2016-01-27T09:52:32.844Z",
|
5
|
+
"entityId": "urn:stormpath:directory:5GbnGg4HIqoFdlRjHndYQC:provider:sp",
|
6
|
+
"assertionConsumerServicePostEndpoint": {
|
7
|
+
"href": "https://api.stormpath.com/v1/directories/5GbnGg4HIqoFdlRjHndYQC/saml/sso/post"
|
8
|
+
},
|
9
|
+
"x509SigningCert": {
|
10
|
+
"href": "https://api.stormpath.com/v1/x509certificates/5LR5SeoE66qXOAfB1lRqYK"
|
11
|
+
}
|
12
|
+
}
|
@@ -99,6 +99,18 @@ describe Stormpath::Resource::Application, :vcr do
|
|
99
99
|
|
100
100
|
end
|
101
101
|
|
102
|
+
describe 'edit authorized_callback_uris' do
|
103
|
+
let(:authorized_callback_uris) { ["https://myapplication.com/whatever/callback", "https://myapplication.com/whatever/callback2"] }
|
104
|
+
|
105
|
+
it 'changes authorized callback uris on application' do
|
106
|
+
application.authorized_callback_uris = authorized_callback_uris
|
107
|
+
response = application.save
|
108
|
+
|
109
|
+
expect(response).to eq application
|
110
|
+
#expect(application.authorized_callback_uris).to eq(authorized_callback_uris)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
102
114
|
|
103
115
|
describe '#create_account' do
|
104
116
|
let(:account) do
|
@@ -122,7 +134,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
122
134
|
|
123
135
|
context 'without registration workflow' do
|
124
136
|
it 'creates an account with workflow disabled' do
|
125
|
-
response = application.create_account account
|
137
|
+
response = application.create_account account
|
126
138
|
|
127
139
|
expect(response).to be_kind_of Stormpath::Resource::Account
|
128
140
|
expect(response.email).to eq(account.email)
|
@@ -243,14 +255,12 @@ describe Stormpath::Resource::Application, :vcr do
|
|
243
255
|
|
244
256
|
describe '#send_password_reset_email' do
|
245
257
|
context 'given an email' do
|
246
|
-
context 'of an
|
258
|
+
context 'of an existing account on the application' do
|
247
259
|
let(:account) { directory.accounts.create build_account }
|
248
260
|
|
249
261
|
let(:sent_to_account) { application.send_password_reset_email account.email }
|
250
262
|
|
251
|
-
after
|
252
|
-
account.delete if account
|
253
|
-
end
|
263
|
+
after { account.delete if account }
|
254
264
|
|
255
265
|
it 'sends a password reset request of the account' do
|
256
266
|
expect(sent_to_account).to be
|
@@ -259,6 +269,27 @@ describe Stormpath::Resource::Application, :vcr do
|
|
259
269
|
end
|
260
270
|
end
|
261
271
|
|
272
|
+
context 'of an existing account not mapped to the application' do
|
273
|
+
let(:account) { other_directory.accounts.create build_account }
|
274
|
+
|
275
|
+
let(:other_directory) do
|
276
|
+
test_api_client.directories.create(
|
277
|
+
name: random_directory_name('password_reset_account_store_href')
|
278
|
+
)
|
279
|
+
end
|
280
|
+
|
281
|
+
after do
|
282
|
+
account.delete
|
283
|
+
other_directory.delete
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'sends a password reset request of the account' do
|
287
|
+
expect do
|
288
|
+
application.send_password_reset_email account.email
|
289
|
+
end.to raise_error Stormpath::Error
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
262
293
|
context 'of a non exisitng account' do
|
263
294
|
it 'raises an exception' do
|
264
295
|
expect do
|
@@ -266,6 +297,224 @@ describe Stormpath::Resource::Application, :vcr do
|
|
266
297
|
end.to raise_error Stormpath::Error
|
267
298
|
end
|
268
299
|
end
|
300
|
+
|
301
|
+
context 'of an existing account on the application with an account store href' do
|
302
|
+
let(:account) { directory.accounts.create build_account }
|
303
|
+
|
304
|
+
let(:sent_to_account) do
|
305
|
+
application.send_password_reset_email(account.email, account_store: { href: directory.href })
|
306
|
+
end
|
307
|
+
|
308
|
+
after { account.delete if account }
|
309
|
+
|
310
|
+
it 'sends a password reset request of the account' do
|
311
|
+
expect(sent_to_account).to be
|
312
|
+
expect(sent_to_account).to be_kind_of Stormpath::Resource::Account
|
313
|
+
expect(sent_to_account.email).to eq(account.email)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'of an existing account on the application with an account store resource object' do
|
318
|
+
let(:account) { directory.accounts.create build_account }
|
319
|
+
|
320
|
+
let(:sent_to_account) do
|
321
|
+
application.send_password_reset_email(account.email, account_store: directory)
|
322
|
+
end
|
323
|
+
|
324
|
+
after { account.delete if account }
|
325
|
+
|
326
|
+
it 'sends a password reset request of the account' do
|
327
|
+
expect(sent_to_account).to be
|
328
|
+
expect(sent_to_account).to be_kind_of Stormpath::Resource::Account
|
329
|
+
expect(sent_to_account.email).to eq(account.email)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
context 'of an existing account not mapped to the application with an account store href' do
|
334
|
+
let(:account) { directory.accounts.create build_account }
|
335
|
+
|
336
|
+
let(:other_directory) do
|
337
|
+
test_api_client.directories.create(
|
338
|
+
name: random_directory_name('password_reset_account_store_href'),
|
339
|
+
description: 'abc'
|
340
|
+
)
|
341
|
+
end
|
342
|
+
|
343
|
+
after do
|
344
|
+
account.delete
|
345
|
+
other_directory.delete
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'sends a password reset request of the account' do
|
349
|
+
expect do
|
350
|
+
application.send_password_reset_email(account.email, account_store: { href: other_directory.href })
|
351
|
+
end.to raise_error Stormpath::Error
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
context 'of an existing account on the application with a non existant account store organization namekey' do
|
356
|
+
let(:account) { directory.accounts.create build_account }
|
357
|
+
|
358
|
+
after do
|
359
|
+
account.delete
|
360
|
+
end
|
361
|
+
|
362
|
+
it 'sends a password reset request of the account' do
|
363
|
+
expect do
|
364
|
+
application.send_password_reset_email(account.email, account_store: { name_key: "NoKey" })
|
365
|
+
end.to raise_error Stormpath::Error
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
context 'of an existing account on the application with a right account store organization namekey' do
|
370
|
+
let(:account) { account_directory.accounts.create build_account }
|
371
|
+
|
372
|
+
let(:account_directory) do
|
373
|
+
test_api_client.directories.create(
|
374
|
+
name: random_directory_name('password_reset_account_store_href')
|
375
|
+
)
|
376
|
+
end
|
377
|
+
|
378
|
+
let(:reloaded_account_directory) do
|
379
|
+
test_api_client.directories.get(account_directory.href)
|
380
|
+
end
|
381
|
+
|
382
|
+
let(:organization_name_key) { "#{random_string}-org-name-key" }
|
383
|
+
|
384
|
+
let(:organization) do
|
385
|
+
test_api_client.organizations.create(
|
386
|
+
name: "#{random_string}_organization_name",
|
387
|
+
name_key: organization_name_key
|
388
|
+
)
|
389
|
+
end
|
390
|
+
|
391
|
+
let(:sent_to_account) do
|
392
|
+
application.send_password_reset_email(account.email, account_store: { name_key: organization.name_key })
|
393
|
+
end
|
394
|
+
|
395
|
+
after do
|
396
|
+
account.delete
|
397
|
+
organization.delete
|
398
|
+
reloaded_account_directory.delete
|
399
|
+
end
|
400
|
+
|
401
|
+
before do
|
402
|
+
test_api_client.organization_account_store_mappings.create(
|
403
|
+
account_store: { href: account_directory.href },
|
404
|
+
organization: { href: organization.href }
|
405
|
+
)
|
406
|
+
|
407
|
+
test_api_client.account_store_mappings.create(application: application, account_store: organization)
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'sends a password reset request of the account' do
|
411
|
+
expect(sent_to_account).to be
|
412
|
+
expect(sent_to_account).to be_kind_of Stormpath::Resource::Account
|
413
|
+
expect(sent_to_account.email).to eq(account.email)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context 'of an existing account on the application with a right account store organization resource object' do
|
418
|
+
let(:account) { account_directory.accounts.create build_account }
|
419
|
+
|
420
|
+
let(:account_directory) do
|
421
|
+
test_api_client.directories.create(
|
422
|
+
name: random_directory_name('password_reset_account_store_href')
|
423
|
+
)
|
424
|
+
end
|
425
|
+
|
426
|
+
let(:reloaded_account_directory) do
|
427
|
+
test_api_client.directories.get(account_directory.href)
|
428
|
+
end
|
429
|
+
|
430
|
+
let(:organization_name_key) { "#{random_string}-org-name-key" }
|
431
|
+
|
432
|
+
let(:organization) do
|
433
|
+
test_api_client.organizations.create(
|
434
|
+
name: "#{random_string}_organization_name",
|
435
|
+
name_key: organization_name_key
|
436
|
+
)
|
437
|
+
end
|
438
|
+
|
439
|
+
let(:sent_to_account) do
|
440
|
+
application.send_password_reset_email(account.email, account_store: organization)
|
441
|
+
end
|
442
|
+
|
443
|
+
after do
|
444
|
+
account.delete
|
445
|
+
organization.delete
|
446
|
+
reloaded_account_directory.delete
|
447
|
+
end
|
448
|
+
|
449
|
+
before do
|
450
|
+
test_api_client.organization_account_store_mappings.create(
|
451
|
+
account_store: { href: account_directory.href },
|
452
|
+
organization: { href: organization.href }
|
453
|
+
)
|
454
|
+
|
455
|
+
test_api_client.account_store_mappings.create(application: application, account_store: organization)
|
456
|
+
end
|
457
|
+
|
458
|
+
it 'sends a password reset request of the account' do
|
459
|
+
expect(sent_to_account).to be
|
460
|
+
expect(sent_to_account).to be_kind_of Stormpath::Resource::Account
|
461
|
+
expect(sent_to_account.email).to eq(account.email)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
context 'of an existing account on the application with a wrong account store organization namekey' do
|
466
|
+
let(:account) { account_directory.accounts.create build_account }
|
467
|
+
|
468
|
+
let(:account_directory) do
|
469
|
+
test_api_client.directories.create(
|
470
|
+
name: random_directory_name('password_reset_account_store_href')
|
471
|
+
)
|
472
|
+
end
|
473
|
+
|
474
|
+
let(:reloaded_account_directory) do
|
475
|
+
test_api_client.directories.get(account_directory.href)
|
476
|
+
end
|
477
|
+
|
478
|
+
let(:organization_name_key) { "#{random_string}-org-name-key" }
|
479
|
+
|
480
|
+
let(:other_organization_name_key) { "#{random_string}-other-org-name-key" }
|
481
|
+
|
482
|
+
let(:organization) do
|
483
|
+
test_api_client.organizations.create(
|
484
|
+
name: "#{random_string}_organization_name",
|
485
|
+
name_key: organization_name_key
|
486
|
+
)
|
487
|
+
end
|
488
|
+
|
489
|
+
let(:other_organization) do
|
490
|
+
test_api_client.organizations.create(
|
491
|
+
name: "#{random_string}_other_organization_name",
|
492
|
+
name_key: other_organization_name_key
|
493
|
+
)
|
494
|
+
end
|
495
|
+
|
496
|
+
after do
|
497
|
+
account.delete
|
498
|
+
organization.delete
|
499
|
+
other_organization.delete
|
500
|
+
reloaded_account_directory.delete
|
501
|
+
end
|
502
|
+
|
503
|
+
before do
|
504
|
+
test_api_client.organization_account_store_mappings.create(
|
505
|
+
account_store: { href: account_directory.href },
|
506
|
+
organization: { href: organization.href }
|
507
|
+
)
|
508
|
+
|
509
|
+
test_api_client.account_store_mappings.create(application: application, account_store: organization)
|
510
|
+
end
|
511
|
+
|
512
|
+
it 'sends a password reset request of the account' do
|
513
|
+
expect do
|
514
|
+
application.send_password_reset_email(account.email, account_store: { name_key: other_organization.name_key })
|
515
|
+
end.to raise_error Stormpath::Error
|
516
|
+
end
|
517
|
+
end
|
269
518
|
end
|
270
519
|
end
|
271
520
|
|
@@ -326,7 +575,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
326
575
|
end
|
327
576
|
|
328
577
|
it 'containes account data' do
|
329
|
-
expect(auth_request.account.href).to eq(account.href)
|
578
|
+
expect(auth_request.account.href).to eq(account.href)
|
330
579
|
end
|
331
580
|
end
|
332
581
|
|
@@ -338,35 +587,131 @@ describe Stormpath::Resource::Application, :vcr do
|
|
338
587
|
})
|
339
588
|
end
|
340
589
|
|
341
|
-
|
342
|
-
test_api_client.
|
343
|
-
|
590
|
+
def create_application_account_store_mapping(application, account_store)
|
591
|
+
test_api_client.account_store_mappings.create(
|
592
|
+
application: application,
|
593
|
+
account_store: account_store
|
594
|
+
)
|
344
595
|
end
|
345
596
|
|
346
|
-
let(:
|
347
|
-
|
348
|
-
|
349
|
-
"P@$$w0rd",
|
350
|
-
account_store: organization.name_key
|
351
|
-
)
|
597
|
+
let(:organization) do
|
598
|
+
test_api_client.organizations.create name: 'test_organization',
|
599
|
+
name_key: "testorganization"
|
352
600
|
end
|
353
601
|
|
354
602
|
let(:auth_request) { application.authenticate_account(username_password_request) }
|
355
603
|
|
356
604
|
before do
|
357
605
|
create_organization_account_store_mapping(organization, directory)
|
606
|
+
create_application_account_store_mapping(application, organization)
|
358
607
|
end
|
359
608
|
|
360
609
|
after do
|
361
610
|
organization.delete if organization
|
362
611
|
end
|
363
612
|
|
364
|
-
|
365
|
-
|
613
|
+
describe 'when sending the proper organization' do
|
614
|
+
describe 'using an organization name_key' do
|
615
|
+
let(:username_password_request) do
|
616
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
617
|
+
account.email, "P@$$w0rd",
|
618
|
+
account_store: { name_key: organization.name_key }
|
619
|
+
)
|
620
|
+
end
|
621
|
+
|
622
|
+
it 'returns login attempt response' do
|
623
|
+
expect(auth_request).to be_kind_of Stormpath::Authentication::AuthenticationResult
|
624
|
+
end
|
625
|
+
|
626
|
+
it 'containes account data' do
|
627
|
+
expect(auth_request.account.href).to eq(account.href)
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
describe 'using an organization href' do
|
632
|
+
let(:username_password_request) do
|
633
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
634
|
+
account.email, "P@$$w0rd",
|
635
|
+
account_store: { href: organization.href }
|
636
|
+
)
|
637
|
+
end
|
638
|
+
|
639
|
+
it 'returns login attempt response' do
|
640
|
+
expect(auth_request).to be_kind_of Stormpath::Authentication::AuthenticationResult
|
641
|
+
end
|
642
|
+
|
643
|
+
it 'containes account data' do
|
644
|
+
expect(auth_request.account.href).to eq(account.href)
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
describe 'using an organization object' do
|
649
|
+
let(:username_password_request) do
|
650
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
651
|
+
account.email, "P@$$w0rd",
|
652
|
+
account_store: organization
|
653
|
+
)
|
654
|
+
end
|
655
|
+
|
656
|
+
it 'returns login attempt response' do
|
657
|
+
expect(auth_request).to be_kind_of Stormpath::Authentication::AuthenticationResult
|
658
|
+
end
|
659
|
+
|
660
|
+
it 'containes account data' do
|
661
|
+
expect(auth_request.account.href).to eq(account.href)
|
662
|
+
end
|
663
|
+
end
|
366
664
|
end
|
367
665
|
|
368
|
-
|
369
|
-
|
666
|
+
describe 'when sending the wrong organization' do
|
667
|
+
describe 'using an organization name_key' do
|
668
|
+
let(:username_password_request) do
|
669
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
670
|
+
account.email, "P@$$w0rd",
|
671
|
+
account_store: { name_key: 'wrong-name-key' }
|
672
|
+
)
|
673
|
+
end
|
674
|
+
|
675
|
+
it 'raises an error' do
|
676
|
+
expect { auth_request }.to raise_error(Stormpath::Error)
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
describe 'using an organization href' do
|
681
|
+
let(:username_password_request) do
|
682
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
683
|
+
account.email, "P@$$w0rd",
|
684
|
+
account_store: { href: other_organization.href }
|
685
|
+
)
|
686
|
+
end
|
687
|
+
|
688
|
+
let(:other_organization) do
|
689
|
+
test_api_client.organizations.create name: 'other_organization',
|
690
|
+
name_key: "other-organization"
|
691
|
+
end
|
692
|
+
|
693
|
+
it 'raises an error' do
|
694
|
+
expect { auth_request }.to raise_error(Stormpath::Error)
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
describe 'using an organization object' do
|
699
|
+
let(:username_password_request) do
|
700
|
+
Stormpath::Authentication::UsernamePasswordRequest.new(
|
701
|
+
account.email, "P@$$w0rd",
|
702
|
+
account_store: other_organization
|
703
|
+
)
|
704
|
+
end
|
705
|
+
|
706
|
+
let(:other_organization) do
|
707
|
+
test_api_client.organizations.create name: 'other_organization',
|
708
|
+
name_key: "other-organization"
|
709
|
+
end
|
710
|
+
|
711
|
+
it 'raises an error' do
|
712
|
+
expect { auth_request }.to raise_error(Stormpath::Error)
|
713
|
+
end
|
714
|
+
end
|
370
715
|
end
|
371
716
|
end
|
372
717
|
|
@@ -381,10 +726,10 @@ describe Stormpath::Resource::Application, :vcr do
|
|
381
726
|
let(:auth_request) { application.authenticate_account(username_password_request) }
|
382
727
|
|
383
728
|
it 'returns stormpath error' do
|
384
|
-
expect {
|
385
|
-
auth_request
|
729
|
+
expect {
|
730
|
+
auth_request
|
386
731
|
}.to raise_error(Stormpath::Error)
|
387
|
-
end
|
732
|
+
end
|
388
733
|
end
|
389
734
|
end
|
390
735
|
|
@@ -506,7 +851,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
506
851
|
expect(error.message).to eq("The specified callback URI (cb_uri) is not valid")
|
507
852
|
expect(error.developer_message).to eq("The specified callback URI (cb_uri) is not valid. Make sure the "\
|
508
853
|
"callback URI specified in your ID Site configuration matches the value specified.")
|
509
|
-
end
|
854
|
+
end
|
510
855
|
end
|
511
856
|
end
|
512
857
|
end
|
@@ -632,7 +977,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
632
977
|
}, test_api_key_secret, 'HS256')
|
633
978
|
}
|
634
979
|
|
635
|
-
it 'should error with the stormpath error' do
|
980
|
+
it 'should error with the stormpath error' do
|
636
981
|
expect {
|
637
982
|
application.handle_id_site_callback(callback_uri_base + jwt_token)
|
638
983
|
}.to raise_error(Stormpath::Error)
|
@@ -676,7 +1021,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
676
1021
|
before do
|
677
1022
|
@site_result = application.handle_id_site_callback(callback_uri_base + jwt_token)
|
678
1023
|
end
|
679
|
-
|
1024
|
+
|
680
1025
|
it 'should return IdSiteResult object' do
|
681
1026
|
expect(@site_result).to be_kind_of(Stormpath::IdSite::IdSiteResult)
|
682
1027
|
end
|
@@ -691,7 +1036,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
691
1036
|
before do
|
692
1037
|
application.accounts.create account_data
|
693
1038
|
end
|
694
|
-
|
1039
|
+
|
695
1040
|
context 'generate access token' do
|
696
1041
|
let(:password_grant_request) { Stormpath::Oauth::PasswordGrantRequest.new account_data[:email], account_data[:password] }
|
697
1042
|
let(:authenticate_oauth) { application.authenticate_oauth(password_grant_request) }
|
@@ -741,7 +1086,7 @@ describe Stormpath::Resource::Application, :vcr do
|
|
741
1086
|
.and_return(Stormpath::Oauth::IdSiteGrant.new({}, application.client))
|
742
1087
|
|
743
1088
|
grant_request = Stormpath::Oauth::IdSiteGrantRequest.new jwt_token
|
744
|
-
response = application.authenticate_oauth(grant_request)
|
1089
|
+
response = application.authenticate_oauth(grant_request)
|
745
1090
|
|
746
1091
|
expect(response).to be(Stormpath::Resource::AccessToken)
|
747
1092
|
end
|
@@ -777,12 +1122,12 @@ describe Stormpath::Resource::Application, :vcr do
|
|
777
1122
|
end
|
778
1123
|
|
779
1124
|
it 'returens success on valid token' do
|
780
|
-
expect(authenticate_oauth.href).not_to be_empty
|
781
|
-
expect(authenticate_oauth.account).not_to be_empty
|
782
|
-
expect(authenticate_oauth.application).not_to be_empty
|
783
|
-
expect(authenticate_oauth.jwt).not_to be_empty
|
784
|
-
expect(authenticate_oauth.tenant).not_to be_empty
|
785
|
-
expect(authenticate_oauth.expanded_jwt).not_to be_empty
|
1125
|
+
expect(authenticate_oauth.href).not_to be_empty
|
1126
|
+
expect(authenticate_oauth.account).not_to be_empty
|
1127
|
+
expect(authenticate_oauth.application).not_to be_empty
|
1128
|
+
expect(authenticate_oauth.jwt).not_to be_empty
|
1129
|
+
expect(authenticate_oauth.tenant).not_to be_empty
|
1130
|
+
expect(authenticate_oauth.expanded_jwt).not_to be_empty
|
786
1131
|
end
|
787
1132
|
end
|
788
1133
|
|