stormpath-rails 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/README.md +1 -1
- data/app/controllers/stormpath/rails/base_controller.rb +34 -0
- data/app/controllers/stormpath/rails/forgot_password/create_controller.rb +16 -2
- data/app/controllers/stormpath/rails/forgot_password/new_controller.rb +17 -3
- data/app/controllers/stormpath/rails/login/create_controller.rb +22 -8
- data/app/controllers/stormpath/rails/login/new_controller.rb +11 -1
- data/app/controllers/stormpath/rails/register/create_controller.rb +26 -3
- data/app/controllers/stormpath/rails/register/new_controller.rb +13 -2
- data/app/controllers/stormpath/rails/verify_email/create_controller.rb +16 -2
- data/app/controllers/stormpath/rails/verify_email/show_controller.rb +13 -0
- data/app/forms/stormpath/rails/login_form.rb +6 -4
- data/app/forms/stormpath/rails/organization_form.rb +26 -0
- data/app/forms/stormpath/rails/registration_form.rb +37 -6
- data/app/forms/stormpath/rails/registration_form_fields.rb +2 -1
- data/app/services/stormpath/rails/organization_resolver.rb +40 -0
- data/app/services/stormpath/rails/resend_email_verification.rb +11 -3
- data/app/services/stormpath/rails/send_password_reset_email.rb +4 -3
- data/app/services/stormpath/rails/url_builder.rb +34 -0
- data/app/views/stormpath/rails/forgot_password/_form.html.erb +24 -0
- data/app/views/stormpath/rails/forgot_password/new.html.erb +6 -24
- data/app/views/stormpath/rails/login/new.html.erb +7 -3
- data/app/views/stormpath/rails/register/new.html.erb +5 -1
- data/app/views/stormpath/rails/shared/_select_organization.html.erb +30 -0
- data/app/views/stormpath/rails/verify_email/_form.html.erb +31 -0
- data/app/views/stormpath/rails/verify_email/new.html.erb +7 -31
- data/docs/changelog.rst +6 -0
- data/lib/generators/stormpath/install/templates/default_config.yml +16 -0
- data/lib/stormpath/rails.rb +1 -0
- data/lib/stormpath/rails/config/dynamic_configuration.rb +5 -0
- data/lib/stormpath/rails/config/multitenancy_verification.rb +37 -0
- data/lib/stormpath/rails/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88eef9432856e3264850f71a1cfb8c436e351645
|
4
|
+
data.tar.gz: 26ec1cf47d26e18ebd6a87fac8a9004fc866d15a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 189c34db894a9640d635fbd00f87206e8cbad70c471e20d8e0dbc003f0a932115e9bd963db93d704bc54c007421efa51ff65860d06ea862e847ed86a1ec60514
|
7
|
+
data.tar.gz: 092c1446f6cf3369d4a8517ea0f297ec94ec10c62116a50d14f71de4e1306b74c73c8e77a5c46de62a3a1678c484ff56fb55b8bae4a3de86514b4582ec12a9ae
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -24,6 +24,40 @@ module Stormpath
|
|
24
24
|
request.format =
|
25
25
|
ContentTypeNegotiator.new(request.headers['HTTP_ACCEPT']).convert_to_symbol
|
26
26
|
end
|
27
|
+
|
28
|
+
def organization_resolution?
|
29
|
+
params.key?(:organization_resolution)
|
30
|
+
end
|
31
|
+
|
32
|
+
def organization_unresolved?
|
33
|
+
stormpath_config.web.multi_tenancy.enabled &&
|
34
|
+
not_on_parent_domain? &&
|
35
|
+
current_organization_name_key.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def not_on_parent_domain?
|
39
|
+
req.host != stormpath_config.web.domain_name
|
40
|
+
end
|
41
|
+
|
42
|
+
def current_organization
|
43
|
+
if stormpath_config.web.multi_tenancy.enabled
|
44
|
+
Stormpath::Rails::OrganizationResolver.new(req, params[:organization_name_key])
|
45
|
+
.organization
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_organization_name_key
|
50
|
+
begin
|
51
|
+
current_organization.try(:name_key)
|
52
|
+
rescue Stormpath::Rails::OrganizationResolver::Error
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
helper_method :current_organization_name_key
|
57
|
+
|
58
|
+
def req
|
59
|
+
request
|
60
|
+
end
|
27
61
|
end
|
28
62
|
end
|
29
63
|
end
|
@@ -4,11 +4,15 @@ module Stormpath
|
|
4
4
|
class CreateController < Stormpath::Rails::BaseController
|
5
5
|
def call
|
6
6
|
begin
|
7
|
-
|
7
|
+
if organization_resolution?
|
8
|
+
OrganizationForm.new(params[:organization_name_key]).save!
|
9
|
+
else
|
10
|
+
SendPasswordResetEmail.new(params[:email], current_organization).call
|
11
|
+
end
|
8
12
|
respond_with_success
|
9
13
|
rescue SendPasswordResetEmail::UnexistingEmailError
|
10
14
|
respond_with_success
|
11
|
-
rescue SendPasswordResetEmail::NoEmailError => error
|
15
|
+
rescue SendPasswordResetEmail::NoEmailError, Stormpath::Rails::OrganizationForm::FormError => error
|
12
16
|
respond_with_error(error)
|
13
17
|
end
|
14
18
|
end
|
@@ -16,6 +20,8 @@ module Stormpath
|
|
16
20
|
private
|
17
21
|
|
18
22
|
def respond_with_success
|
23
|
+
return redirect_to subdomain_forgot_password_url if organization_resolution?
|
24
|
+
|
19
25
|
respond_to do |format|
|
20
26
|
format.html { redirect_to stormpath_config.web.forgot_password.next_uri }
|
21
27
|
format.json { render nothing: true, status: 200 }
|
@@ -31,6 +37,14 @@ module Stormpath
|
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
40
|
+
|
41
|
+
def subdomain_forgot_password_url
|
42
|
+
UrlBuilder.create(
|
43
|
+
req,
|
44
|
+
"#{params[:organization_name_key]}.#{stormpath_config.web.domain_name}",
|
45
|
+
stormpath_config.web.forgot_password.uri
|
46
|
+
)
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -3,11 +3,25 @@ module Stormpath
|
|
3
3
|
module ForgotPassword
|
4
4
|
class NewController < Stormpath::Rails::BaseController
|
5
5
|
def call
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if organization_unresolved?
|
7
|
+
redirect_to(parent_forgot_password_url)
|
8
|
+
else
|
9
|
+
respond_to do |format|
|
10
|
+
format.json { render nothing: true, status: 404 }
|
11
|
+
format.html { render stormpath_config.web.forgot_password.view }
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parent_forgot_password_url
|
19
|
+
UrlBuilder.create(
|
20
|
+
req,
|
21
|
+
stormpath_config.web.domain_name,
|
22
|
+
stormpath_config.web.forgot_password.uri
|
23
|
+
)
|
24
|
+
end
|
11
25
|
end
|
12
26
|
end
|
13
27
|
end
|
@@ -7,9 +7,9 @@ module Stormpath
|
|
7
7
|
def call
|
8
8
|
begin
|
9
9
|
form.save!
|
10
|
-
set_cookies
|
10
|
+
set_cookies if account_login?
|
11
11
|
respond_with_success
|
12
|
-
rescue Stormpath::Error, LoginForm::FormError, SocialLoginForm::FormError => error
|
12
|
+
rescue Stormpath::Error, LoginForm::FormError, SocialLoginForm::FormError, OrganizationForm::FormError, OrganizationResolver::Error => error
|
13
13
|
respond_with_error(error)
|
14
14
|
end
|
15
15
|
end
|
@@ -19,12 +19,18 @@ module Stormpath
|
|
19
19
|
def form
|
20
20
|
@form ||= if social_login?
|
21
21
|
SocialLoginForm.new(provider, access_token, cookies)
|
22
|
+
elsif organization_resolution?
|
23
|
+
OrganizationForm.new(params[:organization_name_key])
|
22
24
|
else
|
23
|
-
LoginForm.new(params[:login],
|
25
|
+
LoginForm.new(params[:login],
|
26
|
+
params[:password],
|
27
|
+
organization_name_key: current_organization.try(:name_key))
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def respond_with_success
|
32
|
+
return redirect_to subdomain_login_url if organization_resolution?
|
33
|
+
|
28
34
|
respond_to do |format|
|
29
35
|
format.html { redirect_to login_redirect_route, notice: 'Successfully signed in' }
|
30
36
|
format.json { render json: serialized_account }
|
@@ -52,11 +58,7 @@ module Stormpath
|
|
52
58
|
end
|
53
59
|
|
54
60
|
def login_redirect_route
|
55
|
-
|
56
|
-
URI(params[:next]).path
|
57
|
-
else
|
58
|
-
stormpath_config.web.login.next_uri
|
59
|
-
end
|
61
|
+
params[:next] ? URI(params[:next]).path : stormpath_config.web.login.next_uri
|
60
62
|
end
|
61
63
|
|
62
64
|
def provider
|
@@ -67,9 +69,21 @@ module Stormpath
|
|
67
69
|
params[:providerData][:accessToken]
|
68
70
|
end
|
69
71
|
|
72
|
+
def account_login?
|
73
|
+
!social_login? && !organization_resolution?
|
74
|
+
end
|
75
|
+
|
70
76
|
def social_login?
|
71
77
|
params[:providerData].present?
|
72
78
|
end
|
79
|
+
|
80
|
+
def subdomain_login_url
|
81
|
+
UrlBuilder.create(
|
82
|
+
req,
|
83
|
+
"#{params[:organization_name_key]}.#{stormpath_config.web.domain_name}",
|
84
|
+
stormpath_config.web.login.uri
|
85
|
+
)
|
86
|
+
end
|
73
87
|
end
|
74
88
|
end
|
75
89
|
end
|
@@ -6,7 +6,9 @@ module Stormpath
|
|
6
6
|
|
7
7
|
def call
|
8
8
|
if stormpath_config.web.id_site.enabled
|
9
|
-
redirect_to
|
9
|
+
redirect_to(callback_url)
|
10
|
+
elsif organization_unresolved?
|
11
|
+
redirect_to(parent_login_url)
|
10
12
|
else
|
11
13
|
respond_to do |format|
|
12
14
|
format.json { render json: LoginNewSerializer.to_h }
|
@@ -23,6 +25,14 @@ module Stormpath
|
|
23
25
|
path: Stormpath::Rails.config.web.id_site.login_uri
|
24
26
|
)
|
25
27
|
end
|
28
|
+
|
29
|
+
def parent_login_url
|
30
|
+
UrlBuilder.create(
|
31
|
+
req,
|
32
|
+
stormpath_config.web.domain_name,
|
33
|
+
stormpath_config.web.login.uri
|
34
|
+
)
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
@@ -4,15 +4,17 @@ module Stormpath
|
|
4
4
|
class CreateController < BaseController
|
5
5
|
def call
|
6
6
|
form.save!
|
7
|
-
login_the_account if
|
7
|
+
login_the_account if valid_for_login?
|
8
8
|
respond_with_success
|
9
|
-
rescue RegistrationForm::FormError => error
|
9
|
+
rescue RegistrationForm::FormError, OrganizationForm::FormError => error
|
10
10
|
respond_with_error(error)
|
11
11
|
end
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def respond_with_success
|
16
|
+
return redirect_to subdomain_register_url if organization_resolution?
|
17
|
+
|
16
18
|
respond_to do |format|
|
17
19
|
format.html { redirect_to success_redirect_route }
|
18
20
|
format.json { render json: serialized_account }
|
@@ -57,6 +59,10 @@ module Stormpath
|
|
57
59
|
render stormpath_config.web.register.view
|
58
60
|
end
|
59
61
|
|
62
|
+
def valid_for_login?
|
63
|
+
auto_login_enabled? && !email_verification_enabled? && !organization_resolution?
|
64
|
+
end
|
65
|
+
|
60
66
|
def auto_login_enabled?
|
61
67
|
stormpath_config.web.register.auto_login
|
62
68
|
end
|
@@ -74,12 +80,29 @@ module Stormpath
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def form
|
77
|
-
@form ||=
|
83
|
+
@form ||= if organization_resolution?
|
84
|
+
OrganizationForm.new(params[:organization_name_key])
|
85
|
+
else
|
86
|
+
RegistrationForm.new(permitted_params)
|
87
|
+
end
|
78
88
|
end
|
79
89
|
|
80
90
|
def excluded_root_params
|
81
91
|
[:controller, :action, :format, :create, :utf8, :button, :authenticity_token]
|
82
92
|
end
|
93
|
+
|
94
|
+
def permitted_params
|
95
|
+
params.except(*excluded_root_params)
|
96
|
+
.merge(organization_name_key: current_organization_name_key)
|
97
|
+
end
|
98
|
+
|
99
|
+
def subdomain_register_url
|
100
|
+
UrlBuilder.create(
|
101
|
+
req,
|
102
|
+
"#{params[:organization_name_key]}.#{stormpath_config.web.domain_name}",
|
103
|
+
stormpath_config.web.register.uri
|
104
|
+
)
|
105
|
+
end
|
83
106
|
end
|
84
107
|
end
|
85
108
|
end
|
@@ -2,11 +2,14 @@ module Stormpath
|
|
2
2
|
module Rails
|
3
3
|
module Register
|
4
4
|
class NewController < BaseController
|
5
|
+
|
5
6
|
def call
|
6
7
|
if stormpath_config.web.id_site.enabled
|
7
|
-
redirect_to
|
8
|
+
redirect_to(callback_url)
|
8
9
|
elsif signed_in?
|
9
|
-
redirect_to
|
10
|
+
redirect_to(root_path)
|
11
|
+
elsif organization_unresolved?
|
12
|
+
redirect_to(parent_register_url)
|
10
13
|
else
|
11
14
|
respond_to do |format|
|
12
15
|
format.json { render json: RegistrationFormSerializer.to_h }
|
@@ -23,6 +26,14 @@ module Stormpath
|
|
23
26
|
path: Stormpath::Rails.config.web.id_site.register_uri
|
24
27
|
)
|
25
28
|
end
|
29
|
+
|
30
|
+
def parent_register_url
|
31
|
+
UrlBuilder.create(
|
32
|
+
req,
|
33
|
+
stormpath_config.web.domain_name,
|
34
|
+
stormpath_config.web.register.uri
|
35
|
+
)
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
28
39
|
end
|
@@ -4,11 +4,15 @@ module Stormpath
|
|
4
4
|
class CreateController < BaseController
|
5
5
|
def call
|
6
6
|
begin
|
7
|
-
|
7
|
+
if organization_resolution?
|
8
|
+
OrganizationForm.new(params[:organization_name_key]).save!
|
9
|
+
else
|
10
|
+
ResendEmailVerification.new(params[:email], current_organization).call
|
11
|
+
end
|
8
12
|
respond_with_success
|
9
13
|
rescue ResendEmailVerification::UnexistingEmailError
|
10
14
|
respond_with_success
|
11
|
-
rescue ResendEmailVerification::NoEmailError => error
|
15
|
+
rescue ResendEmailVerification::NoEmailError, Stormpath::Rails::OrganizationForm::FormError => error
|
12
16
|
respond_with_error(error)
|
13
17
|
end
|
14
18
|
end
|
@@ -16,6 +20,8 @@ module Stormpath
|
|
16
20
|
private
|
17
21
|
|
18
22
|
def respond_with_success
|
23
|
+
return redirect_to subdomain_verify_email_url if organization_resolution?
|
24
|
+
|
19
25
|
respond_to do |format|
|
20
26
|
format.html { redirect_to "#{stormpath_config.web.login.uri}?status=unverified" }
|
21
27
|
format.json { render nothing: true }
|
@@ -31,6 +37,14 @@ module Stormpath
|
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
40
|
+
|
41
|
+
def subdomain_verify_email_url
|
42
|
+
UrlBuilder.create(
|
43
|
+
req,
|
44
|
+
"#{params[:organization_name_key]}.#{stormpath_config.web.domain_name}",
|
45
|
+
stormpath_config.web.verify_email.uri
|
46
|
+
)
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -4,8 +4,11 @@ module Stormpath
|
|
4
4
|
class ShowController < BaseController
|
5
5
|
def call
|
6
6
|
begin
|
7
|
+
return redirect_to(parent_verify_email_url) if organization_unresolved?
|
8
|
+
|
7
9
|
account = VerifyEmailToken.new(params[:sptoken]).call
|
8
10
|
login_the_account(account) if stormpath_config.web.register.auto_login
|
11
|
+
|
9
12
|
respond_with_success
|
10
13
|
rescue InvalidSptokenError, NoSptokenError => error
|
11
14
|
respond_to_error(error)
|
@@ -23,6 +26,8 @@ module Stormpath
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def respond_with_success
|
29
|
+
return redirect_to parent_verify_email_url if organization_resolution?
|
30
|
+
|
26
31
|
respond_to do |format|
|
27
32
|
format.html { redirect_to success_redirect_route }
|
28
33
|
format.json { render nothing: true, status: 200 }
|
@@ -45,6 +50,14 @@ module Stormpath
|
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
53
|
+
|
54
|
+
def parent_verify_email_url
|
55
|
+
UrlBuilder.create(
|
56
|
+
req,
|
57
|
+
stormpath_config.web.domain_name,
|
58
|
+
stormpath_config.web.verify_email.uri
|
59
|
+
)
|
60
|
+
end
|
48
61
|
end
|
49
62
|
end
|
50
63
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Stormpath
|
2
2
|
module Rails
|
3
3
|
class LoginForm
|
4
|
-
attr_accessor :login, :password
|
5
|
-
attr_accessor :authentication_result
|
4
|
+
attr_accessor :login, :password, :authentication_result, :organization_name_key
|
6
5
|
delegate :account, to: :authentication_result
|
7
6
|
|
8
|
-
def initialize(login, password)
|
7
|
+
def initialize(login, password, options = {})
|
9
8
|
@login = login
|
10
9
|
@password = password
|
10
|
+
@organization_name_key = options[:organization_name_key]
|
11
11
|
validate_login_presence
|
12
12
|
validate_password_presence
|
13
13
|
end
|
@@ -39,7 +39,9 @@ module Stormpath
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def password_grant_request
|
42
|
-
Stormpath::Oauth::PasswordGrantRequest.new(login,
|
42
|
+
Stormpath::Oauth::PasswordGrantRequest.new(login,
|
43
|
+
password,
|
44
|
+
organization_name_key: organization_name_key)
|
43
45
|
end
|
44
46
|
|
45
47
|
def application
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Stormpath
|
2
|
+
module Rails
|
3
|
+
class OrganizationForm
|
4
|
+
attr_reader :name_key
|
5
|
+
|
6
|
+
def initialize(name_key)
|
7
|
+
@name_key = name_key
|
8
|
+
raise FormError, "Organization Name Key can't be blank" if name_key.blank?
|
9
|
+
end
|
10
|
+
|
11
|
+
class FormError < ArgumentError
|
12
|
+
def status
|
13
|
+
400
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def save!
|
18
|
+
begin
|
19
|
+
Stormpath::Rails::OrganizationResolver.new(OpenStruct.new(subdomains: [name_key])).organization
|
20
|
+
rescue Stormpath::Rails::OrganizationResolver::Error
|
21
|
+
raise FormError, 'Organization could not be found'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,7 +3,7 @@ module Stormpath
|
|
3
3
|
class RegistrationForm
|
4
4
|
include ActiveModel::Model
|
5
5
|
attr_accessor(*RegistrationFormFields.enabled_field_names)
|
6
|
-
attr_accessor :account
|
6
|
+
attr_accessor :account, :organization_name_key
|
7
7
|
|
8
8
|
validate :validate_presence_of_required_attributes
|
9
9
|
validate :validate_password_repeated_twice_matches?
|
@@ -22,7 +22,7 @@ module Stormpath
|
|
22
22
|
params = params.except(:customData).merge(custom_data_params)
|
23
23
|
params = params.stringify_keys.transform_keys(&:underscore).symbolize_keys
|
24
24
|
|
25
|
-
arbitrary_param_names = params.keys - RegistrationFormFields.enabled_field_names
|
25
|
+
arbitrary_param_names = params.keys - RegistrationFormFields.enabled_field_names.push(:organization_name_key)
|
26
26
|
|
27
27
|
if arbitrary_param_names.any?
|
28
28
|
raise ArbitraryDataSubmitted, "Can't submit arbitrary data: #{arbitrary_param_names.join(', ')}"
|
@@ -35,9 +35,7 @@ module Stormpath
|
|
35
35
|
return false if invalid?
|
36
36
|
|
37
37
|
begin
|
38
|
-
self.account =
|
39
|
-
Stormpath::Resource::Account.new(stormpath_registration_params)
|
40
|
-
)
|
38
|
+
self.account = account_resource
|
41
39
|
rescue Stormpath::Error => error
|
42
40
|
errors.add(:base, error.message) && false
|
43
41
|
end
|
@@ -50,6 +48,38 @@ module Stormpath
|
|
50
48
|
|
51
49
|
private
|
52
50
|
|
51
|
+
def account_resource
|
52
|
+
account_store.accounts.create(new_account)
|
53
|
+
end
|
54
|
+
|
55
|
+
def account_store
|
56
|
+
organization_resolved? ? organization : Stormpath::Rails::Client.application
|
57
|
+
end
|
58
|
+
|
59
|
+
def new_account
|
60
|
+
Stormpath::Resource::Account.new(stormpath_registration_params)
|
61
|
+
end
|
62
|
+
|
63
|
+
def organization_resolved?
|
64
|
+
if multitenancy_enabled?
|
65
|
+
organization.present? ? true : raise(FormError, 'Organization not found.')
|
66
|
+
else
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def multitenancy_enabled?
|
72
|
+
Stormpath::Rails.config.web.multi_tenancy.enabled
|
73
|
+
end
|
74
|
+
|
75
|
+
def organization
|
76
|
+
begin
|
77
|
+
@organization ||= Stormpath::Rails::Client.client.organizations.search(name_key: organization_name_key).first
|
78
|
+
rescue Stormpath::Error
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
53
83
|
def validate_presence_of_required_attributes
|
54
84
|
RegistrationFormFields.required_fields.each do |required_field, properties|
|
55
85
|
if send(required_field).blank?
|
@@ -65,7 +95,8 @@ module Stormpath
|
|
65
95
|
end
|
66
96
|
|
67
97
|
def stormpath_registration_params
|
68
|
-
predefined_registration_params.merge(custom_data: custom_registration_params
|
98
|
+
predefined_registration_params.merge(custom_data: custom_registration_params,
|
99
|
+
organization_name_key: organization_name_key)
|
69
100
|
end
|
70
101
|
|
71
102
|
def predefined_registration_params
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Stormpath
|
2
|
+
module Rails
|
3
|
+
class OrganizationResolver
|
4
|
+
attr_reader :subdomain_name, :organization_name_key
|
5
|
+
|
6
|
+
def initialize(request, organization_name_key = nil)
|
7
|
+
@subdomain_name = request.subdomains.first
|
8
|
+
@organization_name_key = organization_name_key
|
9
|
+
end
|
10
|
+
|
11
|
+
def organization
|
12
|
+
find_organization(subdomain_name) || find_organization(organization_name_key) || raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
class Error < ArgumentError
|
16
|
+
def status
|
17
|
+
400
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def find_organization(name_key)
|
24
|
+
return if name_key.nil?
|
25
|
+
|
26
|
+
application.account_store_mappings.find do |mapping|
|
27
|
+
mapping.account_store.try(:name_key) == name_key
|
28
|
+
end.try(:account_store)
|
29
|
+
end
|
30
|
+
|
31
|
+
def raise_error
|
32
|
+
raise Error, "Organization couldn't be resolved"
|
33
|
+
end
|
34
|
+
|
35
|
+
def application
|
36
|
+
Stormpath::Rails::Client.application
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -3,16 +3,17 @@ module Stormpath
|
|
3
3
|
class ResendEmailVerification
|
4
4
|
PROPERTY_VALUE_DOES_NOT_MATCH_A_STORMPATH_RESOURCE_CODE = 2016
|
5
5
|
|
6
|
-
attr_reader :email
|
6
|
+
attr_reader :email, :account_store
|
7
7
|
|
8
|
-
def initialize(email)
|
8
|
+
def initialize(email, account_store = nil)
|
9
9
|
raise(NoEmailError, 'Email parameter not provided.') if email.blank?
|
10
10
|
@email = email
|
11
|
+
@account_store = account_store
|
11
12
|
end
|
12
13
|
|
13
14
|
def call
|
14
15
|
begin
|
15
|
-
application.verification_emails.create(
|
16
|
+
application.verification_emails.create(email_verification_params)
|
16
17
|
rescue Stormpath::Error => error
|
17
18
|
if error.code == PROPERTY_VALUE_DOES_NOT_MATCH_A_STORMPATH_RESOURCE_CODE
|
18
19
|
raise UnexistingEmailError, error.message
|
@@ -22,6 +23,13 @@ module Stormpath
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
def email_verification_params
|
27
|
+
{}.tap do |body|
|
28
|
+
body[:login] = email
|
29
|
+
body[:account_store] = { name_key: account_store.name_key } if account_store.present?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
25
33
|
def application
|
26
34
|
Stormpath::Rails::Client.application
|
27
35
|
end
|
@@ -3,16 +3,17 @@ module Stormpath
|
|
3
3
|
class SendPasswordResetEmail
|
4
4
|
PROPERTY_VALUE_DOES_NOT_MATCH_A_STORMPATH_RESOURCE_CODE = 2016
|
5
5
|
|
6
|
-
attr_reader :email
|
6
|
+
attr_reader :email, :account_store
|
7
7
|
|
8
|
-
def initialize(email)
|
8
|
+
def initialize(email, account_store = nil)
|
9
9
|
raise(NoEmailError, 'Email parameter not provided.') if email.blank?
|
10
10
|
@email = email
|
11
|
+
@account_store = account_store
|
11
12
|
end
|
12
13
|
|
13
14
|
def call
|
14
15
|
begin
|
15
|
-
application.send_password_reset_email(email)
|
16
|
+
application.send_password_reset_email(email, account_store: account_store)
|
16
17
|
rescue Stormpath::Error => error
|
17
18
|
if error.code == PROPERTY_VALUE_DOES_NOT_MATCH_A_STORMPATH_RESOURCE_CODE
|
18
19
|
raise UnexistingEmailError, error.message
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Stormpath
|
2
|
+
module Rails
|
3
|
+
class UrlBuilder
|
4
|
+
attr_reader :request, :host, :path
|
5
|
+
|
6
|
+
def initialize(request, host, path)
|
7
|
+
@request = request
|
8
|
+
@host = host
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(request, host, path)
|
13
|
+
new(request, host, path).url
|
14
|
+
end
|
15
|
+
|
16
|
+
def url
|
17
|
+
request_scheme_builder.build(host_and_path).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def request_scheme_builder
|
23
|
+
request.scheme == 'https' ? URI::HTTPS : URI::HTTP
|
24
|
+
end
|
25
|
+
|
26
|
+
def host_and_path
|
27
|
+
{
|
28
|
+
host: host,
|
29
|
+
path: path
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="email-password-area col-xs-12 large col-sm-12">
|
2
|
+
<div class="header">
|
3
|
+
<span>Forgot your password?</span>
|
4
|
+
<p>Enter your email address below to reset your password. You will be sent an email which you will need to open to continue. You may need to check your spam folder.</p>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<% if flash[:error] %>
|
8
|
+
<div class="alert alert-danger bad-login">
|
9
|
+
<p><%= flash[:error] %></p>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<%= form_for :password, html: { class: "login-form form-horizontal" }, url: forgot_password_path do |form| %>
|
14
|
+
<div class="form-group group-email">
|
15
|
+
<%= form.label :email, class: "col-sm-4" %>
|
16
|
+
<div class="col-sm-8">
|
17
|
+
<%= form.email_field :email, placeholder: 'Email', class: "form-control", name: :email %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
<div>
|
21
|
+
<%= button_tag "Submit", class: "login btn btn-login btn-sp-green", type: "submit" %>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
@@ -12,31 +12,13 @@
|
|
12
12
|
<% end %>
|
13
13
|
|
14
14
|
<div class="box row">
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
<% if flash[:error] %>
|
22
|
-
<div class="alert alert-danger bad-login">
|
23
|
-
<p><%= flash[:error] %></p>
|
24
|
-
</div>
|
25
|
-
<% end %>
|
26
|
-
|
27
|
-
<%= form_for :password, html: { class: "login-form form-horizontal" }, url: forgot_password_path do |form| %>
|
28
|
-
<div class="form-group group-email">
|
29
|
-
<%= form.label :email, class: "col-sm-4" %>
|
30
|
-
<div class="col-sm-8">
|
31
|
-
<%= form.email_field :email, placeholder: 'Email', class: "form-control", name: :email %>
|
32
|
-
</div>
|
33
|
-
</div>
|
34
|
-
<div>
|
35
|
-
<%= button_tag "Submit", :class => "login btn btn-login btn-sp-green", :type => "submit" %>
|
36
|
-
</div>
|
37
|
-
<% end %>
|
38
|
-
</div>
|
15
|
+
<% if Stormpath::Rails.config.web.multi_tenancy.enabled && current_organization_name_key.nil? %>
|
16
|
+
<%= render partial: 'stormpath/rails/shared/select_organization', locals: { url: forgot_password_path } %>
|
17
|
+
<% else %>
|
18
|
+
<%= render partial: 'stormpath/rails/forgot_password/form' %>
|
19
|
+
<% end %>
|
39
20
|
</div>
|
21
|
+
|
40
22
|
<% if Stormpath::Rails.config.web.login.enabled %>
|
41
23
|
<%= link_to "Back to Log In", new_login_path, class: "forgot" %>
|
42
24
|
<% end %>
|
@@ -2,10 +2,14 @@
|
|
2
2
|
<div class="va-wrapper">
|
3
3
|
<div class="view login-view container">
|
4
4
|
<div class="box row">
|
5
|
-
|
5
|
+
<% if Stormpath::Rails.config.web.multi_tenancy.enabled && current_organization_name_key.nil? %>
|
6
|
+
<%= render partial: 'stormpath/rails/shared/select_organization', locals: {url: login_path(next: params[:next])} %>
|
7
|
+
<% else %>
|
8
|
+
<%= render partial: 'stormpath/rails/login/form' %>
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
<% if Stormpath::Rails.config.web.has_social_providers %>
|
11
|
+
<%= render 'stormpath/rails/shared/social_login' %>
|
12
|
+
<% end %>
|
9
13
|
<% end %>
|
10
14
|
</div>
|
11
15
|
|
@@ -2,7 +2,11 @@
|
|
2
2
|
<div class="va-wrapper">
|
3
3
|
<div class="view registration-view container">
|
4
4
|
<div class="box row">
|
5
|
-
|
5
|
+
<% if Stormpath::Rails.config.web.multi_tenancy.enabled && current_organization_name_key.nil? %>
|
6
|
+
<%= render partial: 'stormpath/rails/shared/select_organization', locals: { url: register_path } %>
|
7
|
+
<% else %>
|
8
|
+
<%= render partial: 'stormpath/rails/register/form' %>
|
9
|
+
<% end %>
|
6
10
|
</div>
|
7
11
|
<% if Stormpath::Rails.config.web.login.enabled %>
|
8
12
|
<%= link_to "Back to Log In", new_login_path, class: "to-login" %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<div class="email-password-area col-xs-12">
|
2
|
+
<div class="header">
|
3
|
+
<span>Select your Organization</span>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<% if flash[:error] %>
|
7
|
+
<div class="alert alert-danger bad-login">
|
8
|
+
<p><%= flash[:error] %></p>
|
9
|
+
</div>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= form_for '', url: url, html: {class: "login-form form-horizontal"} do |form| %>
|
13
|
+
<%= form.hidden_field :organization_resolution %>
|
14
|
+
<div class="form-group group-email">
|
15
|
+
<%= form.label :organization_name_key, 'Enter your organization name to continue', class: 'col-sm-12' %>
|
16
|
+
<div class="<%= input_class %>">
|
17
|
+
<%= form.text_field :organization_name_key,
|
18
|
+
value: params[:organization_name_key],
|
19
|
+
name: :organization_name_key,
|
20
|
+
placeholder: 'e.g. my-company',
|
21
|
+
required: true,
|
22
|
+
class: "form-control"
|
23
|
+
%>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<div>
|
27
|
+
<%= button_tag 'Submit', class: 'login btn btn-login btn-sp-green', type: 'submit' %>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
30
|
+
</div>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<div class="email-password-area col-xs-12 large col-sm-12">
|
2
|
+
<div class="header">
|
3
|
+
<span>Resend Account Verification Email?</span>
|
4
|
+
<% if params[:sptoken].nil? %>
|
5
|
+
<p>
|
6
|
+
Enter your email address below and we'll resend your account
|
7
|
+
verification email. You will be sent an email which you will
|
8
|
+
need to open to continue. You may need to check your spam
|
9
|
+
folder.
|
10
|
+
</p>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<% if flash[:error] %>
|
15
|
+
<div class="alert alert-danger bad-login">
|
16
|
+
<p><%= flash[:error] %></p>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= form_for :verify_email, html: { class: "login-form form-horizontal" }, url: verify_email_path do |form| %>
|
21
|
+
<div class="form-group group-email">
|
22
|
+
<%= form.label :email, class: "col-sm-4" %>
|
23
|
+
<div class="col-sm-8">
|
24
|
+
<%= form.text_field :email, placeholder: 'Email', class: "form-control", name: :email, type: :email, required: true %>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
<div>
|
28
|
+
<%= button_tag "Submit", :class => "login btn btn-login btn-sp-green", :type => "submit" %>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
31
|
+
</div>
|
@@ -10,39 +10,15 @@
|
|
10
10
|
</div>
|
11
11
|
</div>
|
12
12
|
<% end %>
|
13
|
-
<div class="box row">
|
14
|
-
<div class="email-password-area col-xs-12 large col-sm-12">
|
15
|
-
<div class="header">
|
16
|
-
<span>Resend Account Verification Email?</span>
|
17
|
-
<% if params[:sptoken].nil? %>
|
18
|
-
<p>
|
19
|
-
Enter your email address below and we'll resend your account
|
20
|
-
verification email. You will be sent an email which you will
|
21
|
-
need to open to continue. You may need to check your spam
|
22
|
-
folder.
|
23
|
-
</p>
|
24
|
-
<% end %>
|
25
|
-
</div>
|
26
|
-
|
27
|
-
<% if flash[:error] %>
|
28
|
-
<div class="alert alert-danger bad-login">
|
29
|
-
<p><%= flash[:error] %></p>
|
30
|
-
</div>
|
31
|
-
<% end %>
|
32
13
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
</div>
|
40
|
-
<div>
|
41
|
-
<%= button_tag "Submit", :class => "login btn btn-login btn-sp-green", :type => "submit" %>
|
42
|
-
</div>
|
43
|
-
<% end %>
|
44
|
-
</div>
|
14
|
+
<div class="box row">
|
15
|
+
<% if Stormpath::Rails.config.web.multi_tenancy.enabled && current_organization_name_key.nil? %>
|
16
|
+
<%= render partial: 'stormpath/rails/shared/select_organization', locals: { url: verify_email_path } %>
|
17
|
+
<% else %>
|
18
|
+
<%= render partial: 'stormpath/rails/verify_email/form' %>
|
19
|
+
<% end %>
|
45
20
|
</div>
|
21
|
+
|
46
22
|
<% if Stormpath::Rails.config.web.login.enabled %>
|
47
23
|
<%= link_to "Back to Log In", new_login_path, class: "forgot" %>
|
48
24
|
<% end %>
|
data/docs/changelog.rst
CHANGED
@@ -6,6 +6,22 @@ stormpath:
|
|
6
6
|
web:
|
7
7
|
basePath: null
|
8
8
|
|
9
|
+
domainName: null # Required if using subdomain-based multi-tenancy
|
10
|
+
|
11
|
+
multiTenancy:
|
12
|
+
|
13
|
+
# When enabled, the framework will require the user to authenticate against
|
14
|
+
# a specific Organization. The authenticated organization is persisted in
|
15
|
+
# the access token that is issued.
|
16
|
+
#
|
17
|
+
# At the moment we only support a sub-domain based strategy, wherby the
|
18
|
+
# user must arrive on the subdomain that correlates with their tenant in
|
19
|
+
# order to authenticate. If they visit the parent domain, they will be
|
20
|
+
# required to identify the organization they wish to use.
|
21
|
+
|
22
|
+
enabled: false
|
23
|
+
strategy: "subdomain"
|
24
|
+
|
9
25
|
oauth2:
|
10
26
|
enabled: true
|
11
27
|
uri: "/oauth/token"
|
data/lib/stormpath/rails.rb
CHANGED
@@ -4,6 +4,7 @@ require 'stormpath/rails/config/read_file'
|
|
4
4
|
require 'stormpath/rails/config/application_resolution'
|
5
5
|
require 'stormpath/rails/config/account_store_verification'
|
6
6
|
require 'stormpath/rails/config/dynamic_configuration'
|
7
|
+
require 'stormpath/rails/config/multitenancy_verification'
|
7
8
|
require 'stormpath/rails/config/social_login_verification'
|
8
9
|
require 'stormpath/rails/configuration'
|
9
10
|
require 'stormpath/rails/router'
|
@@ -17,6 +17,7 @@ module Stormpath
|
|
17
17
|
def initialize(static_config)
|
18
18
|
@static_config = static_config
|
19
19
|
proccess_account_store_verification
|
20
|
+
process_multitenancy_verification if static_config.stormpath.web.multi_tenancy.enabled
|
20
21
|
end
|
21
22
|
|
22
23
|
def app
|
@@ -69,6 +70,10 @@ module Stormpath
|
|
69
70
|
).call
|
70
71
|
end
|
71
72
|
|
73
|
+
def process_multitenancy_verification
|
74
|
+
MultitenancyVerification.new(static_config.stormpath.web).call
|
75
|
+
end
|
76
|
+
|
72
77
|
def social_login_verification
|
73
78
|
@social_login_verification ||= SocialLoginVerification.new(app.href)
|
74
79
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Stormpath
|
2
|
+
module Rails
|
3
|
+
module Config
|
4
|
+
class MultitenancyVerification
|
5
|
+
attr_reader :web_config
|
6
|
+
|
7
|
+
def initialize(web_config)
|
8
|
+
@web_config = web_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
verify_multitenancy_set_correctly
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def verify_multitenancy_set_correctly
|
18
|
+
return if multitenancy_set_correctly?
|
19
|
+
raise(
|
20
|
+
InvalidConfiguration,
|
21
|
+
"Multitenancy is not set correctly in the configuration file. It needs to have a domainName and multitenancy strategy set to 'subdomain'"
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def multitenancy_set_correctly?
|
26
|
+
multitenancy.enabled &&
|
27
|
+
multitenancy.strategy == 'subdomain' &&
|
28
|
+
!web_config.domain_name.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def multitenancy
|
32
|
+
web_config.multi_tenancy
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stormpath-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nenad Nikolic
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: stormpath-sdk
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- app/controllers/stormpath/rails/verify_email/create_controller.rb
|
135
135
|
- app/controllers/stormpath/rails/verify_email/show_controller.rb
|
136
136
|
- app/forms/stormpath/rails/login_form.rb
|
137
|
+
- app/forms/stormpath/rails/organization_form.rb
|
137
138
|
- app/forms/stormpath/rails/registration_form.rb
|
138
139
|
- app/forms/stormpath/rails/registration_form_fields.rb
|
139
140
|
- app/forms/stormpath/rails/social_login_form.rb
|
@@ -152,14 +153,17 @@ files:
|
|
152
153
|
- app/services/stormpath/rails/delete_access_token.rb
|
153
154
|
- app/services/stormpath/rails/delete_refresh_token.rb
|
154
155
|
- app/services/stormpath/rails/forgot_password_token_verification.rb
|
156
|
+
- app/services/stormpath/rails/organization_resolver.rb
|
155
157
|
- app/services/stormpath/rails/password_change.rb
|
156
158
|
- app/services/stormpath/rails/refresh_token_authentication.rb
|
157
159
|
- app/services/stormpath/rails/resend_email_verification.rb
|
158
160
|
- app/services/stormpath/rails/send_password_reset_email.rb
|
159
161
|
- app/services/stormpath/rails/token_and_cookies_cleaner.rb
|
160
162
|
- app/services/stormpath/rails/token_cookie_setter.rb
|
163
|
+
- app/services/stormpath/rails/url_builder.rb
|
161
164
|
- app/services/stormpath/rails/verify_email_token.rb
|
162
165
|
- app/views/stormpath/rails/change_password/new.html.erb
|
166
|
+
- app/views/stormpath/rails/forgot_password/_form.html.erb
|
163
167
|
- app/views/stormpath/rails/forgot_password/new.html.erb
|
164
168
|
- app/views/stormpath/rails/layouts/stormpath.html.erb
|
165
169
|
- app/views/stormpath/rails/login/_form.html.erb
|
@@ -167,7 +171,9 @@ files:
|
|
167
171
|
- app/views/stormpath/rails/register/_form.html.erb
|
168
172
|
- app/views/stormpath/rails/register/new.html.erb
|
169
173
|
- app/views/stormpath/rails/shared/_input.html.erb
|
174
|
+
- app/views/stormpath/rails/shared/_select_organization.html.erb
|
170
175
|
- app/views/stormpath/rails/shared/_social_login.html.erb
|
176
|
+
- app/views/stormpath/rails/verify_email/_form.html.erb
|
171
177
|
- app/views/stormpath/rails/verify_email/new.html.erb
|
172
178
|
- bin/console
|
173
179
|
- bin/rails
|
@@ -241,6 +247,7 @@ files:
|
|
241
247
|
- lib/stormpath/rails/config/account_store_verification.rb
|
242
248
|
- lib/stormpath/rails/config/application_resolution.rb
|
243
249
|
- lib/stormpath/rails/config/dynamic_configuration.rb
|
250
|
+
- lib/stormpath/rails/config/multitenancy_verification.rb
|
244
251
|
- lib/stormpath/rails/config/read_file.rb
|
245
252
|
- lib/stormpath/rails/config/social_login_verification.rb
|
246
253
|
- lib/stormpath/rails/configuration.rb
|