searls-auth 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/README.md +162 -0
- data/app/controllers/searls/auth/base_controller.rb +42 -21
- data/app/controllers/searls/auth/email_verifications_controller.rb +57 -0
- data/app/controllers/searls/auth/logins_controller.rb +60 -39
- data/app/controllers/searls/auth/registrations_controller.rb +84 -32
- data/app/controllers/searls/auth/requests_password_resets_controller.rb +55 -0
- data/app/controllers/searls/auth/resets_passwords_controller.rb +73 -0
- data/app/controllers/searls/auth/settings_controller.rb +83 -0
- data/app/controllers/searls/auth/verifications_controller.rb +31 -61
- data/app/helpers/searls/auth/application_helper.rb +9 -5
- data/app/mailers/searls/auth/base_mailer.rb +1 -1
- data/app/mailers/searls/auth/email_verification_mailer.rb +29 -0
- data/app/mailers/searls/auth/login_link_mailer.rb +3 -3
- data/app/mailers/searls/auth/password_reset_mailer.rb +29 -0
- data/app/views/searls/auth/email_verification_mailer/verification_email.html.erb +23 -0
- data/app/views/searls/auth/email_verification_mailer/verification_email.text.erb +6 -0
- data/app/views/searls/auth/login_link_mailer/login_link.html.erb +5 -5
- data/app/views/searls/auth/login_link_mailer/login_link.text.erb +4 -5
- data/app/views/searls/auth/logins/show.html.erb +12 -4
- data/app/views/searls/auth/password_reset_mailer/password_reset.html.erb +23 -0
- data/app/views/searls/auth/password_reset_mailer/password_reset.text.erb +6 -0
- data/app/views/searls/auth/registrations/pending_email_verification.html.erb +12 -0
- data/app/views/searls/auth/registrations/show.html.erb +1 -2
- data/app/views/searls/auth/requests_password_resets/show.html.erb +17 -0
- data/app/views/searls/auth/resets_passwords/show.html.erb +26 -0
- data/app/views/searls/auth/settings/edit.html.erb +31 -0
- data/app/views/searls/auth/shared/_login_fields.html.erb +11 -0
- data/app/views/searls/auth/shared/_register_fields.html.erb +15 -0
- data/config/routes.rb +11 -0
- data/lib/searls/auth/authenticates_user.rb +54 -10
- data/lib/searls/auth/builds_target_redirect_url.rb +72 -0
- data/lib/searls/auth/config.rb +259 -12
- data/lib/searls/auth/creates_user.rb +12 -4
- data/lib/searls/auth/delivers_password_reset.rb +18 -0
- data/lib/searls/auth/emails_link.rb +2 -2
- data/lib/searls/auth/emails_verification.rb +33 -0
- data/lib/searls/auth/parses_time_safely.rb +32 -0
- data/lib/searls/auth/railtie.rb +0 -1
- data/lib/searls/auth/resets_password.rb +41 -0
- data/lib/searls/auth/updates_settings.rb +149 -0
- data/lib/searls/auth/version.rb +1 -1
- data/lib/searls/auth.rb +62 -13
- metadata +23 -1
@@ -0,0 +1,55 @@
|
|
1
|
+
module Searls
|
2
|
+
module Auth
|
3
|
+
class RequestsPasswordResetsController < BaseController
|
4
|
+
before_action :ensure_password_reset_enabled
|
5
|
+
before_action :clear_email_otp_from_session!, only: [:show, :create]
|
6
|
+
|
7
|
+
def show
|
8
|
+
render Searls::Auth.config.password_reset_request_view, layout: Searls::Auth.config.layout
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
email = params[:email].to_s.strip
|
13
|
+
user = Searls::Auth.config.user_finder_by_email.call(email)
|
14
|
+
|
15
|
+
if proceed_with_password_reset_request?(user) && deliverable_user?(user)
|
16
|
+
Searls::Auth::DeliversPasswordReset.new.deliver(
|
17
|
+
user:,
|
18
|
+
redirect_path: params[:redirect_path],
|
19
|
+
redirect_subdomain: params[:redirect_subdomain]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
flash[:notice] = Searls::Auth.config.resolve(:flash_notice_after_password_reset_email, params)
|
24
|
+
redirect_to searls_auth.password_reset_request_path(
|
25
|
+
email: email,
|
26
|
+
redirect_path: params[:redirect_path],
|
27
|
+
redirect_subdomain: params[:redirect_subdomain]
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def ensure_password_reset_enabled
|
34
|
+
return if Searls::Auth.config.password_reset_enabled?
|
35
|
+
|
36
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_password_reset_not_enabled, params)
|
37
|
+
redirect_to searls_auth.login_path(
|
38
|
+
redirect_path: params[:redirect_path],
|
39
|
+
redirect_subdomain: params[:redirect_subdomain]
|
40
|
+
)
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def deliverable_user?(user)
|
45
|
+
return false if user.blank?
|
46
|
+
Searls::Auth.config.password_present?(user)
|
47
|
+
end
|
48
|
+
|
49
|
+
def proceed_with_password_reset_request?(user)
|
50
|
+
result = Searls::Auth.config.before_password_reset.call(user, params, self)
|
51
|
+
!(result == false || result == :halt)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Searls
|
2
|
+
module Auth
|
3
|
+
class ResetsPasswordsController < BaseController
|
4
|
+
before_action :ensure_password_reset_enabled
|
5
|
+
before_action :load_user_from_token
|
6
|
+
before_action :clear_email_otp_from_session!, only: [:show, :update]
|
7
|
+
|
8
|
+
def show
|
9
|
+
@token = params[:token]
|
10
|
+
@user_email = @user.email
|
11
|
+
render Searls::Auth.config.password_reset_edit_view, layout: Searls::Auth.config.layout
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
result = ResetsPassword.new.reset(
|
16
|
+
user: @user,
|
17
|
+
password: params[:password],
|
18
|
+
password_confirmation: params[:password_confirmation]
|
19
|
+
)
|
20
|
+
|
21
|
+
if result.success?
|
22
|
+
handle_successful_reset(result.user)
|
23
|
+
else
|
24
|
+
flash.now[:alert] = Array(result.errors).first
|
25
|
+
@token = params[:token]
|
26
|
+
@user_email = @user.email
|
27
|
+
render Searls::Auth.config.password_reset_edit_view, layout: Searls::Auth.config.layout, status: :unprocessable_content
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def ensure_password_reset_enabled
|
34
|
+
return if Searls::Auth.config.password_reset_enabled?
|
35
|
+
|
36
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_password_reset_not_enabled, params)
|
37
|
+
redirect_to searls_auth.login_path(
|
38
|
+
redirect_path: params[:redirect_path],
|
39
|
+
redirect_subdomain: params[:redirect_subdomain]
|
40
|
+
)
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_user_from_token
|
45
|
+
token = params[:token].to_s
|
46
|
+
@user = Searls::Auth.config.password_reset_token_finder.call(token)
|
47
|
+
return if @user.present?
|
48
|
+
|
49
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_password_reset_token_invalid, params)
|
50
|
+
redirect_to searls_auth.password_reset_request_path(
|
51
|
+
redirect_path: params[:redirect_path],
|
52
|
+
redirect_subdomain: params[:redirect_subdomain]
|
53
|
+
)
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def handle_successful_reset(user)
|
58
|
+
flash[:notice] = Searls::Auth.config.resolve(:flash_notice_after_password_reset, user, params)
|
59
|
+
|
60
|
+
if Searls::Auth.config.auto_login_after_password_reset
|
61
|
+
session[:user_id] = user.id
|
62
|
+
session[:has_logged_in_before] = true
|
63
|
+
redirect_after_login(user)
|
64
|
+
else
|
65
|
+
redirect_to searls_auth.login_path(
|
66
|
+
redirect_path: params[:redirect_path],
|
67
|
+
redirect_subdomain: params[:redirect_subdomain]
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Searls
|
2
|
+
module Auth
|
3
|
+
class SettingsController < BaseController
|
4
|
+
before_action :ensure_password_auth_enabled
|
5
|
+
before_action :ensure_authenticated_user
|
6
|
+
before_action :load_settings_user
|
7
|
+
|
8
|
+
helper_method :settings_user, :password_on_file?
|
9
|
+
|
10
|
+
def edit
|
11
|
+
render :edit, layout: Searls::Auth.config.layout
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
permitted_params = settings_params.to_h
|
16
|
+
result = UpdatesSettings.new(
|
17
|
+
user: settings_user,
|
18
|
+
params: permitted_params
|
19
|
+
).update
|
20
|
+
|
21
|
+
@settings_user = result.user
|
22
|
+
@password_on_file = nil
|
23
|
+
|
24
|
+
if result.success?
|
25
|
+
flash[:notice] = Searls::Auth.config.resolve(:flash_notice_after_settings_update, settings_user, params)
|
26
|
+
else
|
27
|
+
# Normally, we would flash.now and render `settings_view`, but this controller is
|
28
|
+
# intended to back forms hosted elsewhere. Redirecting keeps the host UI in control
|
29
|
+
# while surfacing validation errors via the session flash.
|
30
|
+
flash[:alert] = Array(result.errors).compact_blank.first
|
31
|
+
end
|
32
|
+
redirect_target = Searls::Auth.config.resolve(
|
33
|
+
:redirect_path_after_settings_change,
|
34
|
+
settings_user, params, request, searls_auth
|
35
|
+
) || searls_auth.edit_settings_path
|
36
|
+
redirect_to redirect_target
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def ensure_password_auth_enabled
|
42
|
+
return if Searls::Auth.config.auth_methods.include?(:password)
|
43
|
+
|
44
|
+
head :not_found
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def ensure_authenticated_user
|
49
|
+
return if session[:user_id].present?
|
50
|
+
|
51
|
+
redirect_to searls_auth.login_path(
|
52
|
+
redirect_path: request.original_fullpath,
|
53
|
+
redirect_subdomain: request.subdomain
|
54
|
+
)
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_settings_user
|
59
|
+
@settings_user = Searls::Auth.config.user_finder_by_id.call(session[:user_id])
|
60
|
+
return if @settings_user.present?
|
61
|
+
|
62
|
+
session.delete(:user_id)
|
63
|
+
redirect_to searls_auth.login_path(
|
64
|
+
redirect_path: request.original_fullpath,
|
65
|
+
redirect_subdomain: request.subdomain
|
66
|
+
)
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_reader :settings_user
|
71
|
+
|
72
|
+
def password_on_file?
|
73
|
+
@password_on_file ||= settings_user && Searls::Auth.config.password_present?(settings_user)
|
74
|
+
end
|
75
|
+
|
76
|
+
def settings_params
|
77
|
+
permitted = [:password, :password_confirmation, :current_password]
|
78
|
+
|
79
|
+
params.fetch(:settings, ActionController::Parameters.new).permit(permitted)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,93 +1,63 @@
|
|
1
1
|
module Searls
|
2
2
|
module Auth
|
3
3
|
class VerificationsController < BaseController
|
4
|
-
before_action :
|
4
|
+
before_action :reset_expired_email_otp
|
5
5
|
|
6
6
|
def show
|
7
|
-
|
7
|
+
if !(Searls::Auth.config.auth_methods & [:email_link, :email_otp]).any?
|
8
|
+
redirect_to searls_auth.login_path(**forwardable_params)
|
9
|
+
else
|
10
|
+
render Searls::Auth.config.verify_view, layout: Searls::Auth.config.layout
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
14
|
def create
|
11
15
|
auth_method = params[:short_code].present? ? :email_otp : :email_link
|
12
|
-
if auth_method == :email_otp && !
|
13
|
-
flash[:
|
14
|
-
return redirect_to searls_auth.login_path(
|
15
|
-
redirect_path: params[:redirect_path],
|
16
|
-
redirect_subdomain: params[:redirect_subdomain]
|
17
|
-
)
|
16
|
+
if auth_method == :email_otp && !Searls::Auth.config.auth_methods.include?(:email_otp)
|
17
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_verify_attempt_invalid_link, params)
|
18
|
+
return redirect_to searls_auth.login_path(**forwardable_params)
|
18
19
|
end
|
19
|
-
if auth_method == :email_link && !
|
20
|
-
flash[:
|
21
|
-
return redirect_to searls_auth.login_path(
|
22
|
-
redirect_path: params[:redirect_path],
|
23
|
-
redirect_subdomain: params[:redirect_subdomain]
|
24
|
-
)
|
20
|
+
if auth_method == :email_link && !Searls::Auth.config.auth_methods.include?(:email_link)
|
21
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_verify_attempt_invalid_link, params)
|
22
|
+
return redirect_to searls_auth.login_path(**forwardable_params)
|
25
23
|
end
|
26
24
|
authenticator = AuthenticatesUser.new
|
27
25
|
result = case auth_method
|
28
26
|
when :email_otp
|
29
|
-
|
30
|
-
authenticator.
|
27
|
+
log_email_otp_verification_attempt!
|
28
|
+
authenticator.authenticate_by_email_otp(params[:short_code], session)
|
31
29
|
when :email_link
|
32
30
|
authenticator.authenticate_by_token(params[:token])
|
33
31
|
end
|
34
32
|
|
35
33
|
if result.success?
|
34
|
+
if [:email_otp, :email_link].include?(auth_method)
|
35
|
+
unless Searls::Auth.config.email_verified_predicate.call(result.user)
|
36
|
+
Searls::Auth.config.email_verified_setter.call(result.user)
|
37
|
+
end
|
38
|
+
end
|
36
39
|
session[:user_id] = result.user.id
|
37
40
|
session[:has_logged_in_before] = true
|
38
|
-
flash[:notice] =
|
39
|
-
|
40
|
-
|
41
|
-
)
|
42
|
-
if params[:redirect_subdomain].present? && params[:redirect_subdomain] != request.subdomain
|
43
|
-
redirect_to generate_full_url(
|
44
|
-
params[:redirect_path],
|
45
|
-
params[:redirect_subdomain]
|
46
|
-
), allow_other_host: true
|
47
|
-
elsif params[:redirect_path].present?
|
48
|
-
redirect_to params[:redirect_path]
|
41
|
+
flash[:notice] = Searls::Auth.config.resolve(:flash_notice_after_login, result.user, params)
|
42
|
+
if (target = target_redirect_url)
|
43
|
+
redirect_with_host_awareness(target)
|
49
44
|
else
|
50
|
-
redirect_to
|
51
|
-
result.user, params, request, main_app)
|
45
|
+
redirect_to Searls::Auth.config.resolve(:redirect_path_after_login, result.user, params, request, main_app)
|
52
46
|
end
|
53
47
|
elsif auth_method == :email_otp
|
54
|
-
if result.
|
55
|
-
|
56
|
-
flash[:
|
57
|
-
|
58
|
-
params
|
59
|
-
)
|
60
|
-
redirect_to searls_auth.login_path(
|
61
|
-
redirect_path: params[:redirect_path],
|
62
|
-
redirect_subdomain: params[:redirect_subdomain]
|
63
|
-
)
|
48
|
+
if result.exceeded_email_otp_attempt_limit?
|
49
|
+
clear_email_otp_from_session!
|
50
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_verify_attempt_exceeds_limit, params)
|
51
|
+
redirect_to searls_auth.login_path(**forwardable_params)
|
64
52
|
else
|
65
|
-
flash[:
|
66
|
-
|
67
|
-
params
|
68
|
-
)
|
69
|
-
render searls_auth_config.verify_view, layout: searls_auth_config.layout, status: :unprocessable_entity
|
53
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_verify_attempt_incorrect_email_otp, params)
|
54
|
+
render Searls::Auth.config.verify_view, layout: Searls::Auth.config.layout, status: :unprocessable_content
|
70
55
|
end
|
71
56
|
else
|
72
|
-
flash[:
|
73
|
-
|
74
|
-
params
|
75
|
-
)
|
76
|
-
redirect_to searls_auth.login_path(
|
77
|
-
redirect_path: params[:redirect_path],
|
78
|
-
redirect_subdomain: params[:redirect_subdomain]
|
79
|
-
)
|
57
|
+
flash[:alert] = Searls::Auth.config.resolve(:flash_error_after_verify_attempt_invalid_link, params)
|
58
|
+
redirect_to searls_auth.login_path(**forwardable_params)
|
80
59
|
end
|
81
60
|
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
def generate_full_url(path, subdomain)
|
86
|
-
port = request.port
|
87
|
-
port_string = (port == 80 || port == 443) ? "" : ":#{port}"
|
88
|
-
|
89
|
-
"#{request.protocol}#{subdomain}.#{request.domain}#{port_string}#{path}"
|
90
|
-
end
|
91
61
|
end
|
92
62
|
end
|
93
63
|
end
|
@@ -25,6 +25,14 @@ module Searls
|
|
25
25
|
routes.register_url(forwardable_params.merge(kwargs))
|
26
26
|
end
|
27
27
|
|
28
|
+
def password_reset_request_path(**kwargs)
|
29
|
+
routes.password_reset_request_path(forwardable_params.merge(kwargs))
|
30
|
+
end
|
31
|
+
|
32
|
+
def password_reset_available?
|
33
|
+
Searls::Auth.config.password_reset_enabled?
|
34
|
+
end
|
35
|
+
|
28
36
|
def login_stimulus_controller
|
29
37
|
"searls-auth-login"
|
30
38
|
end
|
@@ -64,11 +72,7 @@ module Searls
|
|
64
72
|
private
|
65
73
|
|
66
74
|
def forwardable_params
|
67
|
-
|
68
|
-
email: params[:email],
|
69
|
-
redirect_path: params[:redirect_path],
|
70
|
-
redirect_subdomain: params[:redirect_subdomain]
|
71
|
-
}.compact_blank
|
75
|
+
@view_context.forwardable_params
|
72
76
|
end
|
73
77
|
|
74
78
|
def params
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Searls
|
2
|
+
module Auth
|
3
|
+
class EmailVerificationMailer < BaseMailer
|
4
|
+
def verification_email
|
5
|
+
@config = Searls::Auth.config
|
6
|
+
@user = params[:user]
|
7
|
+
@token = params[:token]
|
8
|
+
@redirect_path = params[:redirect_path]
|
9
|
+
@redirect_subdomain = params[:redirect_subdomain]
|
10
|
+
|
11
|
+
mail(
|
12
|
+
to: format_to(@user),
|
13
|
+
subject: mail_subject,
|
14
|
+
template_path: @config.mail_email_verification_template_path,
|
15
|
+
template_name: @config.mail_email_verification_template_name
|
16
|
+
) do |format|
|
17
|
+
format.html { render layout: @config.mail_layout }
|
18
|
+
format.text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def mail_subject
|
25
|
+
"Verify your #{searls_auth_helper.rpad(@config.app_name)}email"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -7,7 +7,7 @@ module Searls
|
|
7
7
|
@token = params[:token]
|
8
8
|
@redirect_path = params[:redirect_path]
|
9
9
|
@redirect_subdomain = params[:redirect_subdomain]
|
10
|
-
@
|
10
|
+
@email_otp = params[:email_otp]
|
11
11
|
|
12
12
|
mail(
|
13
13
|
to: format_to(@user),
|
@@ -24,8 +24,8 @@ module Searls
|
|
24
24
|
|
25
25
|
def mail_subject
|
26
26
|
methods = Searls::Auth.config.auth_methods
|
27
|
-
if methods.include?(:email_otp) && @
|
28
|
-
"Your #{searls_auth_helper.rpad(@config.app_name)}login code is #{@
|
27
|
+
if methods.include?(:email_otp) && @email_otp.present?
|
28
|
+
"Your #{searls_auth_helper.rpad(@config.app_name)}login code is #{@email_otp}"
|
29
29
|
else
|
30
30
|
"Your #{searls_auth_helper.rpad(@config.app_name)}login link"
|
31
31
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Searls
|
2
|
+
module Auth
|
3
|
+
class PasswordResetMailer < BaseMailer
|
4
|
+
def password_reset
|
5
|
+
@config = Searls::Auth.config
|
6
|
+
@user = params[:user]
|
7
|
+
@token = params[:token]
|
8
|
+
@redirect_path = params[:redirect_path]
|
9
|
+
@redirect_subdomain = params[:redirect_subdomain]
|
10
|
+
|
11
|
+
mail(
|
12
|
+
to: format_to(@user),
|
13
|
+
subject: mail_subject,
|
14
|
+
template_path: @config.mail_password_reset_template_path,
|
15
|
+
template_name: @config.mail_password_reset_template_name
|
16
|
+
) do |format|
|
17
|
+
format.html { render layout: @config.mail_layout }
|
18
|
+
format.text
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def mail_subject
|
25
|
+
"Reset your #{searls_auth_helper.rpad(@config.app_name)}password"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= content_for :width, 480 %>
|
2
|
+
<p>
|
3
|
+
<% if (user_name = searls_auth_helper.attr_for(@user, @config.user_name_method)).present? %>
|
4
|
+
Hello, <strong><%= user_name %></strong>!
|
5
|
+
<% else %>
|
6
|
+
Hello!
|
7
|
+
<% end %>
|
8
|
+
</p>
|
9
|
+
<p style="margin-top: 1rem;">
|
10
|
+
Please verify your email address to keep your account secure:
|
11
|
+
<div style="margin-top: 2rem; text-align: center;">
|
12
|
+
<%= link_to searls_auth.verify_email_url({
|
13
|
+
token: @token,
|
14
|
+
redirect_path: @redirect_path,
|
15
|
+
redirect_subdomain: @redirect_subdomain
|
16
|
+
}.compact_blank) do %>
|
17
|
+
<span style="width: 70%; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); display: inline-block; padding-left: 2rem; padding-right: 2rem; padding-top: 1rem; padding-bottom: 1rem; font-size: 1.5rem; font-weight: 700; border-radius: 0.75rem; background-color: <%= @config.email_button_color %>; color: white;">Verify email address</span>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</p>
|
21
|
+
<p style="margin-top: 2rem; font-size: 0.875rem; color: #6b7280;">
|
22
|
+
If you didn't create an account or change your email, you can ignore this message.
|
23
|
+
</p>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Hello<% if (user_name = searls_auth_helper.attr_for(@user, @config.user_name_method)).present? %>, <%= user_name %><% end %>!
|
2
|
+
|
3
|
+
Verify your email using this link:
|
4
|
+
<%= searls_auth.verify_email_url({ token: @token, redirect_path: @redirect_path, redirect_subdomain: @redirect_subdomain }.compact_blank) %>
|
5
|
+
|
6
|
+
If you didn't ask for this, you can ignore this email.
|
@@ -6,7 +6,7 @@
|
|
6
6
|
Hello!
|
7
7
|
<% end %>
|
8
8
|
</p>
|
9
|
-
<% if
|
9
|
+
<% if @config.auth_methods.include?(:email_link) %>
|
10
10
|
<p style="margin-top: 1rem;">
|
11
11
|
You can log in by clicking this button:
|
12
12
|
<div style="margin-top: 2rem; text-align: center;">
|
@@ -18,17 +18,17 @@
|
|
18
18
|
<span style="width: 70%; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); display: inline-block; padding-left: 2rem; padding-right: 2rem; padding-top: 1rem; padding-bottom: 1rem; font-size: 1.5rem; font-weight: 700; border-radius: 0.75rem; background-color: <%= @config.email_button_color %>; color: white;">Log in</span>
|
19
19
|
<% end %>
|
20
20
|
<div style="margin-top: 0.5rem; font-size: 0.875rem; color: #6b7280;">
|
21
|
-
(This link
|
21
|
+
(This link expires soon, so we recommend using it right away.)
|
22
22
|
</div>
|
23
23
|
</div>
|
24
24
|
</p>
|
25
25
|
<% end %>
|
26
|
-
<% if
|
26
|
+
<% if @config.auth_methods.include?(:email_otp) && @email_otp.present? %>
|
27
27
|
<p style="margin-top: 2rem;">
|
28
28
|
You can log in by entering this code:
|
29
29
|
<div style="margin-top: 2rem; text-align: center;">
|
30
30
|
<span id="one-time-code" style="width: 70%; display: inline-block; padding-left: 2rem; padding-right: 2rem; padding-top: 1rem; padding-bottom: 1rem; font-size: 1.5rem; font-weight: 700; border: 1px solid; border-radius: 0.75rem; background-color: #f3f4f6; border-color: #e5e7eb;">
|
31
|
-
<%= @
|
31
|
+
<%= @email_otp %>
|
32
32
|
</span>
|
33
33
|
<div style="margin-top: 0.5rem; font-size: 0.875rem; color: #6b7280;">
|
34
34
|
(So will this code.)
|
@@ -37,5 +37,5 @@
|
|
37
37
|
</p>
|
38
38
|
<% end %>
|
39
39
|
<p style="margin-top: 2rem; font-size: 0.875rem; color: #6b7280;">
|
40
|
-
p.s. Didn't try to log in? You can safely ignore this email.
|
40
|
+
p.s. Didn't try to log in? You can safely ignore this email.
|
41
41
|
</p>
|
@@ -4,7 +4,7 @@ Hi, <%= user_name %>!
|
|
4
4
|
Hello!
|
5
5
|
<% end %>
|
6
6
|
|
7
|
-
<% if
|
7
|
+
<% if @config.auth_methods.include?(:email_link) %>
|
8
8
|
You can log in by visiting this URL for your <%= searls_auth_helper.rpad(@config.app_name) %>account:
|
9
9
|
|
10
10
|
<%= searls_auth.verify_token_url({
|
@@ -14,12 +14,11 @@ You can log in by visiting this URL for your <%= searls_auth_helper.rpad(@config
|
|
14
14
|
}.compact_blank) %>
|
15
15
|
<% end %>
|
16
16
|
|
17
|
-
<% if
|
17
|
+
<% if @config.auth_methods.include?(:email_otp) && @email_otp.present? %>
|
18
18
|
|
19
19
|
You can log in by entering this code:
|
20
20
|
|
21
|
-
<%= @
|
21
|
+
<%= @email_otp %>
|
22
22
|
<% end %>
|
23
23
|
|
24
|
-
Didn't try to log in? You can safely ignore this email
|
25
|
-
happening, please let us know at #{@config.support_email_address}" if @config.support_email_address.present? %>
|
24
|
+
Didn't try to log in? You can safely ignore this email.
|
@@ -3,12 +3,20 @@
|
|
3
3
|
<%= form_with url: searls_auth.login_path, method: :post, data: {controller: searls_auth_helper.login_stimulus_controller} do |f| %>
|
4
4
|
<%= f.hidden_field :redirect_path, value: params[:redirect_path] %>
|
5
5
|
<%= f.hidden_field :redirect_subdomain, value: params[:redirect_subdomain] %>
|
6
|
-
<%= f
|
7
|
-
|
8
|
-
|
6
|
+
<%= render "searls/auth/shared/login_fields", f: f %>
|
7
|
+
<div>
|
8
|
+
<%= f.submit "Log in" %>
|
9
|
+
<% if Searls::Auth.config.auth_methods.include?(:password) && (Searls::Auth.config.auth_methods & [:email_link, :email_otp]).any? %>
|
10
|
+
<%= button_tag "Send login email", name: "send_login_email", value: "1", type: "submit" %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
<% if searls_auth_helper.password_reset_available? %>
|
14
|
+
<div>
|
15
|
+
<%= link_to "Forgot your password?", searls_auth_helper.password_reset_request_path %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
9
18
|
<% end %>
|
10
19
|
|
11
20
|
<p>
|
12
21
|
Not registered yet? <%= link_to "Sign up", searls_auth_helper.register_path %> instead!
|
13
22
|
</p>
|
14
|
-
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= content_for :width, 480 %>
|
2
|
+
<p>
|
3
|
+
<% if (user_name = searls_auth_helper.attr_for(@user, @config.user_name_method)).present? %>
|
4
|
+
Hello, <strong><%= user_name %></strong>!
|
5
|
+
<% else %>
|
6
|
+
Hello!
|
7
|
+
<% end %>
|
8
|
+
</p>
|
9
|
+
<p style="margin-top: 1rem;">
|
10
|
+
You can reset your password by clicking this button:
|
11
|
+
<div style="margin-top: 2rem; text-align: center;">
|
12
|
+
<%= link_to password_reset_edit_url({
|
13
|
+
token: @token,
|
14
|
+
redirect_path: @redirect_path,
|
15
|
+
redirect_subdomain: @redirect_subdomain
|
16
|
+
}.compact_blank) do %>
|
17
|
+
<span style="width: 70%; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); display: inline-block; padding-left: 2rem; padding-right: 2rem; padding-top: 1rem; padding-bottom: 1rem; font-size: 1.5rem; font-weight: 700; border-radius: 0.75rem; background-color: <%= @config.email_button_color %>; color: white;">Reset password</span>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</p>
|
21
|
+
<p style="margin-top: 2rem; font-size: 0.875rem; color: #6b7280;">
|
22
|
+
If you didn't ask to reset your password, you can ignore this email.
|
23
|
+
</p>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Hello<% if (user_name = searls_auth_helper.attr_for(@user, @config.user_name_method)).present? %>, <%= user_name %><% end %>!
|
2
|
+
|
3
|
+
Reset your password using this link:
|
4
|
+
<%= password_reset_edit_url({ token: @token, redirect_path: @redirect_path, redirect_subdomain: @redirect_subdomain }.compact_blank) %>
|
5
|
+
|
6
|
+
If you didn't ask for this, you can ignore this email.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Check your email!</h1>
|
2
|
+
<p>
|
3
|
+
We sent a verification link to <strong><%= h(session[:searls_auth_pending_email]) || h(params[:email]) %></strong>.
|
4
|
+
Click the link to verify your email before you can log in with a password.
|
5
|
+
If it doesn’t arrive in a minute, check spam or resend it below.
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p style="margin-top: 1rem;">
|
9
|
+
<%= link_to "Resend verification email",
|
10
|
+
searls_auth.resend_email_verification_path(**forwardable_params),
|
11
|
+
data: { turbo_method: :patch } %>
|
12
|
+
</p>
|
@@ -3,8 +3,7 @@
|
|
3
3
|
<%= form_with url: searls_auth.register_path, data: {controller: searls_auth_helper.login_stimulus_controller} do |f| %>
|
4
4
|
<%= f.hidden_field :redirect_path, value: params[:redirect_path] %>
|
5
5
|
<%= f.hidden_field :redirect_subdomain, value: params[:redirect_subdomain] %>
|
6
|
-
<%= f
|
7
|
-
<%= f.email_field :email, value: params[:email], required: true, data: searls_auth_helper.email_field_stimulus_data %>
|
6
|
+
<%= render "searls/auth/shared/register_fields", f: f %>
|
8
7
|
<%= f.submit "Register" %>
|
9
8
|
<% end %>
|
10
9
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Forgot your password?</h1>
|
2
|
+
|
3
|
+
<%= form_with url: searls_auth.password_reset_request_path, method: :post, data: {controller: searls_auth_helper.login_stimulus_controller} do |f| %>
|
4
|
+
<%= f.hidden_field :redirect_path, value: params[:redirect_path] %>
|
5
|
+
<%= f.hidden_field :redirect_subdomain, value: params[:redirect_subdomain] %>
|
6
|
+
<div>
|
7
|
+
<%= f.label :email, "Email address" %>
|
8
|
+
<%= f.email_field :email, required: true, value: params[:email], autocomplete: "email" %>
|
9
|
+
</div>
|
10
|
+
<div>
|
11
|
+
<%= f.submit "Send reset instructions" %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<p>
|
16
|
+
Remembered your password? <%= link_to "Log in", searls_auth_helper.login_path %> instead.
|
17
|
+
</p>
|