searls-auth 0.1.1 → 1.0.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +185 -1
  5. data/app/controllers/searls/auth/base_controller.rb +42 -21
  6. data/app/controllers/searls/auth/email_verifications_controller.rb +57 -0
  7. data/app/controllers/searls/auth/logins_controller.rb +61 -35
  8. data/app/controllers/searls/auth/registrations_controller.rb +84 -32
  9. data/app/controllers/searls/auth/requests_password_resets_controller.rb +55 -0
  10. data/app/controllers/searls/auth/resets_passwords_controller.rb +73 -0
  11. data/app/controllers/searls/auth/settings_controller.rb +83 -0
  12. data/app/controllers/searls/auth/verifications_controller.rb +37 -53
  13. data/app/helpers/searls/auth/application_helper.rb +9 -5
  14. data/app/mailers/searls/auth/base_mailer.rb +1 -1
  15. data/app/mailers/searls/auth/email_verification_mailer.rb +29 -0
  16. data/app/mailers/searls/auth/login_link_mailer.rb +13 -2
  17. data/app/mailers/searls/auth/password_reset_mailer.rb +29 -0
  18. data/app/views/searls/auth/email_verification_mailer/verification_email.html.erb +23 -0
  19. data/app/views/searls/auth/email_verification_mailer/verification_email.text.erb +6 -0
  20. data/app/views/searls/auth/login_link_mailer/login_link.html.erb +29 -25
  21. data/app/views/searls/auth/login_link_mailer/login_link.text.erb +9 -5
  22. data/app/views/searls/auth/logins/show.html.erb +12 -4
  23. data/app/views/searls/auth/password_reset_mailer/password_reset.html.erb +23 -0
  24. data/app/views/searls/auth/password_reset_mailer/password_reset.text.erb +6 -0
  25. data/app/views/searls/auth/registrations/pending_email_verification.html.erb +12 -0
  26. data/app/views/searls/auth/registrations/show.html.erb +1 -2
  27. data/app/views/searls/auth/requests_password_resets/show.html.erb +17 -0
  28. data/app/views/searls/auth/resets_passwords/show.html.erb +26 -0
  29. data/app/views/searls/auth/settings/edit.html.erb +31 -0
  30. data/app/views/searls/auth/shared/_login_fields.html.erb +11 -0
  31. data/app/views/searls/auth/shared/_register_fields.html.erb +15 -0
  32. data/app/views/searls/auth/verifications/show.html.erb +20 -20
  33. data/config/routes.rb +11 -0
  34. data/lib/searls/auth/authenticates_user.rb +54 -10
  35. data/lib/searls/auth/builds_target_redirect_url.rb +72 -0
  36. data/lib/searls/auth/config.rb +246 -10
  37. data/lib/searls/auth/creates_user.rb +12 -4
  38. data/lib/searls/auth/delivers_password_reset.rb +18 -0
  39. data/lib/searls/auth/emails_link.rb +3 -3
  40. data/lib/searls/auth/emails_verification.rb +33 -0
  41. data/lib/searls/auth/parses_time_safely.rb +34 -0
  42. data/lib/searls/auth/railtie.rb +0 -1
  43. data/lib/searls/auth/resets_password.rb +41 -0
  44. data/lib/searls/auth/updates_settings.rb +149 -0
  45. data/lib/searls/auth/version.rb +1 -1
  46. data/lib/searls/auth.rb +63 -13
  47. data/script/setup +1 -6
  48. data/script/test +1 -1
  49. metadata +24 -2
@@ -0,0 +1,18 @@
1
+ module Searls
2
+ module Auth
3
+ class DeliversPasswordReset
4
+ Result = Struct.new(:success?, keyword_init: true)
5
+
6
+ def deliver(user:, redirect_path: nil, redirect_subdomain: nil)
7
+ token = Searls::Auth.config.password_reset_token_generator.call(user)
8
+ PasswordResetMailer.with(
9
+ user:,
10
+ token:,
11
+ redirect_path:,
12
+ redirect_subdomain:
13
+ ).password_reset.deliver_later
14
+ Result.new(success?: true)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,11 +1,11 @@
1
1
  module Searls
2
2
  module Auth
3
3
  class EmailsLink
4
- def email(user:, short_code:, redirect_path: nil, redirect_subdomain: nil)
4
+ def email(user:, email_otp:, redirect_path: nil, redirect_subdomain: nil)
5
5
  LoginLinkMailer.with(
6
6
  user:,
7
- token: generate_token!(user),
8
- short_code:,
7
+ token: (Searls::Auth.config.auth_methods.include?(:email_link) ? generate_token!(user) : nil),
8
+ email_otp: (Searls::Auth.config.auth_methods.include?(:email_otp) ? email_otp : nil),
9
9
  redirect_path:,
10
10
  redirect_subdomain:
11
11
  ).login_link.deliver_later
@@ -0,0 +1,33 @@
1
+ module Searls
2
+ module Auth
3
+ class EmailsVerification
4
+ def email(user:, redirect_path: nil, redirect_subdomain: nil)
5
+ EmailVerificationMailer.with(
6
+ user:,
7
+ token: generate_token!(user),
8
+ redirect_path:,
9
+ redirect_subdomain:
10
+ ).verification_email.deliver_later
11
+ end
12
+
13
+ private
14
+
15
+ def generate_token!(user)
16
+ Searls::Auth.config.token_generator.call(user)
17
+ rescue KeyError => e
18
+ raise Error, <<~MSG
19
+ Secure token generation for user failed!
20
+
21
+ Message: #{e.message}
22
+ User: #{user.inspect}
23
+
24
+ This can probably be fixed by adding a line like this to your #{user.class.name} class:
25
+
26
+ generates_token_for :email_auth, expires_in: 30.minutes
27
+
28
+ Otherwise, you may want to override searls-auth's "token_generator" setting with a proc of your own.
29
+ MSG
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ require "active_support/time"
2
+
3
+ module Searls
4
+ module Auth
5
+ class ParsesTimeSafely
6
+ def parse(input)
7
+ return nil if input.nil?
8
+
9
+ case input
10
+ when String
11
+ parse_string(input)
12
+ when Integer, Float
13
+ Time.at(input).in_time_zone
14
+ else
15
+ if input.respond_to?(:in_time_zone)
16
+ input.in_time_zone
17
+ else
18
+ parse_string(input.to_s)
19
+ end
20
+ end
21
+ rescue ArgumentError, TypeError, NoMethodError
22
+ nil
23
+ end
24
+
25
+ private
26
+
27
+ def parse_string(s)
28
+ if !(stripped = s.strip).empty?
29
+ Time.zone.parse(stripped)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -13,7 +13,6 @@ module Searls
13
13
 
14
14
  # Initialize configuration defaults
15
15
  initializer "searls.auth.configure" do |app|
16
- # Set up any configuration defaults here
17
16
  end
18
17
  end
19
18
  end
@@ -0,0 +1,41 @@
1
+ module Searls
2
+ module Auth
3
+ class ResetsPassword
4
+ Result = Struct.new(:success?, :errors, :user, keyword_init: true)
5
+
6
+ def reset(user:, password:, password_confirmation:)
7
+ configuration = Searls::Auth.config
8
+
9
+ if password.blank?
10
+ message = configuration.resolve(:flash_error_after_password_reset_password_blank, {})
11
+ return Result.new(success?: false, errors: Array(message), user: user)
12
+ end
13
+
14
+ if password != password_confirmation
15
+ message = configuration.resolve(:flash_error_after_password_reset_password_mismatch, {})
16
+ return Result.new(success?: false, errors: Array(message), user: user)
17
+ end
18
+
19
+ configuration.password_setter.call(user, password)
20
+ if user.respond_to?(:password_confirmation=)
21
+ user.password_confirmation = password_confirmation
22
+ end
23
+
24
+ if user.save
25
+ configuration.after_login_success.call(user)
26
+ Result.new(success?: true, user: user, errors: [])
27
+ else
28
+ Result.new(success?: false, user: user, errors: simplified_error_messages(user))
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def simplified_error_messages(model)
35
+ model.errors.details.keys.map { |attr|
36
+ model.errors.full_messages_for(attr).first
37
+ }.compact
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,149 @@
1
+ module Searls
2
+ module Auth
3
+ class UpdatesSettings
4
+ Result = Struct.new(
5
+ :success?,
6
+ :errors,
7
+ :user,
8
+ :password_changed?,
9
+ keyword_init: true
10
+ )
11
+
12
+ def initialize(user:, params:)
13
+ @user = user
14
+ @params = params || {}
15
+ @errors = []
16
+ @password_changed = false
17
+ end
18
+
19
+ def update
20
+ enforce_current_password_requirement
21
+
22
+ handle_password_change if errors.empty?
23
+
24
+ return failure_result unless errors.empty?
25
+
26
+ if changes_applied?
27
+ if user.save
28
+ Result.new(
29
+ success?: true,
30
+ user: user,
31
+ errors: [],
32
+ password_changed?: @password_changed
33
+ )
34
+ else
35
+ Result.new(
36
+ success?: false,
37
+ user: user,
38
+ errors: simplified_error_messages(user)
39
+ )
40
+ end
41
+ else
42
+ Result.new(success?: true, user: user, errors: [], password_changed?: false)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :user, :params, :errors
49
+
50
+ def enforce_current_password_requirement
51
+ return unless password_present?
52
+ return unless password_change_requested?
53
+
54
+ if current_password.blank?
55
+ errors << array_wrap(Searls::Auth.config.resolve(:flash_error_after_settings_current_password_missing, {}))
56
+ errors.flatten!
57
+ return
58
+ end
59
+
60
+ begin
61
+ verified = Searls::Auth.config.password_verifier.call(user, current_password)
62
+ rescue NameError
63
+ errors << array_wrap(Searls::Auth.config.resolve(:flash_error_after_password_misconfigured, {}))
64
+ errors.flatten!
65
+ return
66
+ end
67
+
68
+ unless verified
69
+ errors << array_wrap(Searls::Auth.config.resolve(:flash_error_after_settings_current_password_invalid, {}))
70
+ errors.flatten!
71
+ end
72
+ end
73
+
74
+ def handle_password_change
75
+ return unless password_change_requested?
76
+
77
+ if new_password.blank?
78
+ errors << array_wrap(Searls::Auth.config.resolve(:flash_error_after_password_reset_password_blank, {}))
79
+ errors.flatten!
80
+ return
81
+ end
82
+
83
+ if new_password != new_password_confirmation
84
+ errors << array_wrap(Searls::Auth.config.resolve(:flash_error_after_password_reset_password_mismatch, {}))
85
+ errors.flatten!
86
+ return
87
+ end
88
+
89
+ Searls::Auth.config.password_setter.call(user, new_password)
90
+ if user.respond_to?(:password_confirmation=)
91
+ user.password_confirmation = new_password_confirmation
92
+ end
93
+ @password_changed = true
94
+ end
95
+
96
+ def password_present?
97
+ Searls::Auth.config.password_present?(user)
98
+ end
99
+
100
+ def password_change_requested?
101
+ new_password.present? || new_password_confirmation.present?
102
+ end
103
+
104
+ def current_password
105
+ param(:current_password).to_s
106
+ end
107
+
108
+ def new_password
109
+ param(:password)
110
+ end
111
+
112
+ def new_password_confirmation
113
+ param(:password_confirmation)
114
+ end
115
+
116
+ def param(key)
117
+ params[key] || params[key.to_s]
118
+ end
119
+
120
+ def changes_applied?
121
+ @password_changed
122
+ end
123
+
124
+ def failure_result
125
+ flattened = errors.flatten.compact_blank
126
+ Result.new(success?: false, user: user, errors: flattened.presence || simplified_error_messages(user))
127
+ end
128
+
129
+ def array_wrap(value)
130
+ case value
131
+ when Array
132
+ value
133
+ when nil
134
+ []
135
+ else
136
+ [value]
137
+ end
138
+ end
139
+
140
+ def simplified_error_messages(model)
141
+ return [] unless model.respond_to?(:errors)
142
+
143
+ model.errors.details.keys.map do |attr|
144
+ model.errors.full_messages_for(attr).first
145
+ end.compact
146
+ end
147
+ end
148
+ end
149
+ end
@@ -1,5 +1,5 @@
1
1
  module Searls
2
2
  module Auth
3
- VERSION = "0.1.1"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
data/lib/searls/auth.rb CHANGED
@@ -1,10 +1,16 @@
1
1
  require_relative "auth/authenticates_user"
2
+ require_relative "auth/parses_time_safely"
2
3
  require_relative "auth/config"
4
+ require_relative "auth/builds_target_redirect_url" if defined?(Rails)
3
5
  require_relative "auth/creates_user" if defined?(Rails)
4
6
  require_relative "auth/emails_link"
7
+ require_relative "auth/emails_verification"
5
8
  require_relative "auth/engine" if defined?(Rails)
6
9
  require_relative "auth/railtie" if defined?(Rails)
7
10
  require_relative "auth/resets_session"
11
+ require_relative "auth/delivers_password_reset"
12
+ require_relative "auth/resets_password"
13
+ require_relative "auth/updates_settings"
8
14
  require_relative "auth/version"
9
15
 
10
16
  module Searls
@@ -12,6 +18,8 @@ module Searls
12
18
  class Error < StandardError; end
13
19
 
14
20
  DEFAULT_CONFIG = {
21
+ auth_methods: [:email_link, :email_otp],
22
+ email_verification_mode: :none,
15
23
  # Data setup
16
24
  user_finder_by_email: ->(email) { User.find_by(email:) },
17
25
  user_finder_by_id: ->(id) { User.find_by(id:) },
@@ -19,34 +27,52 @@ module Searls
19
27
  user_initializer: ->(params) { User.new(email: params[:email]) },
20
28
  user_name_method: "name",
21
29
  token_generator: ->(user) { user.generate_token_for(:email_auth) },
22
- token_expiry_minutes: 30,
30
+ email_otp_expiry_minutes: 30,
31
+ password_verifier: ->(user, password) { user.authenticate(password) },
32
+ password_setter: ->(user, password) { user.password = password },
33
+ password_reset_token_generator: ->(user) { user.generate_token_for(:password_reset) },
34
+ password_reset_token_finder: ->(token) { User.find_by_token_for(:password_reset, token) },
35
+ before_password_reset: ->(user, params, controller) { true },
36
+ password_reset_enabled: true,
37
+ email_verified_predicate: ->(user) { user.respond_to?(:email_verified_at) && user.email_verified_at.present? },
38
+ email_verified_setter: ->(user, time = Time.current) { user.respond_to?(:email_verified_at) ? user.update!(email_verified_at: time) : true },
39
+ password_present_predicate: ->(user) { user.respond_to?(:password_digest) && user.password_digest.present? },
23
40
  # Controller setup
24
41
  preserve_session_keys_after_logout: [],
25
- max_allowed_short_code_attempts: 10,
42
+ max_allowed_email_otp_attempts: 10,
26
43
  # View setup
27
44
  layout: "application",
28
45
  register_view: "searls/auth/registrations/show",
29
46
  login_view: "searls/auth/logins/show",
30
47
  verify_view: "searls/auth/verifications/show",
48
+ pending_email_verification_view: "searls/auth/registrations/pending_email_verification",
49
+ password_reset_request_view: "searls/auth/requests_password_resets/show",
50
+ password_reset_edit_view: "searls/auth/resets_passwords/show",
31
51
  mail_layout: "searls/auth/layouts/mailer",
32
52
  mail_login_template_path: "searls/auth/login_link_mailer",
33
53
  mail_login_template_name: "login_link",
54
+ mail_password_reset_template_path: "searls/auth/password_reset_mailer",
55
+ mail_password_reset_template_name: "password_reset",
56
+ mail_email_verification_template_path: "searls/auth/email_verification_mailer",
57
+ mail_email_verification_template_name: "verification_email",
34
58
  # Route setup
35
59
  redirect_path_after_register: ->(user, params, request, routes) {
36
60
  # Not every app defines a root_path, so guarding here:
37
61
  routes.respond_to?(:root_path) ? routes.root_path : "/"
38
62
  },
39
- default_redirect_path_after_login: ->(user, params, request, routes) {
63
+ redirect_path_after_login: ->(user, params, request, routes) {
40
64
  # Not every app defines a root_path, so guarding here:
41
65
  routes.respond_to?(:root_path) ? routes.root_path : "/"
42
66
  },
67
+ redirect_path_after_settings_change: ->(user, params, request, routes) {
68
+ routes.respond_to?(:edit_settings_path) ? routes.edit_settings_path : "/settings"
69
+ },
43
70
  # Hook setup
44
71
  validate_registration: ->(user, params, errors) { errors },
45
- after_login_success: nil,
72
+ after_login_success: ->(user) {},
46
73
  # Branding setup
47
74
  app_name: nil,
48
75
  app_url: nil,
49
- support_email_address: nil,
50
76
  email_background_color: "#d8d7ed",
51
77
  email_button_color: "#c664f3",
52
78
  email_banner_image_path: nil,
@@ -55,23 +81,47 @@ module Searls
55
81
  flash_error_after_register_attempt: ->(error_messages, login_path, params) { error_messages },
56
82
  flash_notice_after_login_attempt: ->(user, params) { "Login details sent to #{params[:email]}" },
57
83
  flash_error_after_login_attempt_unknown_email: ->(register_path, params) {
58
- "We don't know that email. <a href=\"#{register_path}\">Sign up</a> instead?".html_safe
84
+ "We don't know that email. <a href=\"#{register_path}\">Sign up</a> instead?"
85
+ },
86
+ flash_error_after_login_attempt_invalid_password: ->(params) { "Invalid password. Try again?" },
87
+ flash_error_after_login_attempt_unverified_email: ->(resend_path, params) {
88
+ "You must verify your email before logging in. <a href=\"#{resend_path}\" data-turbo-method=\"patch\">Resend verification email</a>"
89
+ },
90
+ flash_notice_after_login_with_unverified_email: ->(resend_path, params) {
91
+ "You are now logged in, but your email is still unverified. <a href=\"#{resend_path}\" data-turbo-method=\"patch\">Resend verification email</a>"
92
+ },
93
+ flash_error_after_password_misconfigured: ->(params) {
94
+ "Password authentication misconfigured. Add `bcrypt` to your Gemfile or override password hooks."
59
95
  },
96
+ flash_error_after_password_reset_token_invalid: ->(params) { "That password reset link is no longer valid. Try again?" },
97
+ flash_error_after_password_reset_password_mismatch: ->(params) { "Passwords must match. Try again?" },
98
+ flash_error_after_password_reset_password_blank: ->(params) { "Password can't be blank. Try again?" },
99
+ flash_error_after_password_reset_not_enabled: ->(params) { "Password resets are unavailable." },
60
100
  flash_notice_after_logout: "You've been logged out",
61
- flash_notice_after_verification: "You are now logged in",
101
+ flash_notice_after_login: "You are now logged in",
102
+ flash_notice_after_verification_email_resent: "Verification email sent",
103
+ flash_notice_after_email_verified: "Email verified",
104
+ flash_notice_after_password_reset_email: ->(params) { "If that email exists, password reset instructions are on the way." },
105
+ flash_notice_after_password_reset: ->(user, params) { "Your password has been reset." },
62
106
  flash_error_after_verify_attempt_exceeds_limit: "Too many verification attempts. Please login again to generate a new code",
63
- flash_error_after_verify_attempt_incorrect_short_code: "We weren't able to log you in with that code. Try again?",
64
- flash_error_after_verify_attempt_invalid_link: "We weren't able to log you in with that link. Try again?"
107
+ flash_error_after_verify_attempt_incorrect_email_otp: "We weren't able to log you in with that code. Try again?",
108
+ flash_error_after_verify_attempt_invalid_link: "We weren't able to log you in with that link. Try again?",
109
+ flash_notice_after_settings_update: ->(user, params) { "Settings updated." },
110
+ flash_error_after_settings_current_password_missing: ->(params) { "Enter your current password to make changes." },
111
+ flash_error_after_settings_current_password_invalid: ->(params) { "That current password doesn't match our records." },
112
+ auto_login_after_password_reset: true
65
113
 
66
114
  }.freeze
67
115
 
68
- CONFIG = Config.new(**DEFAULT_CONFIG)
69
- def self.configure(&blk)
70
- yield CONFIG
116
+ C_O_N_F_I_G__D_O_N_T_R_E_F_E_R_E_N_C_E__T_H_I_S__D_I_R_E_C_T_L_Y_L_O_L = Config.new(**DEFAULT_CONFIG)
117
+ def self.configure
118
+ yield C_O_N_F_I_G__D_O_N_T_R_E_F_E_R_E_N_C_E__T_H_I_S__D_I_R_E_C_T_L_Y_L_O_L
119
+ C_O_N_F_I_G__D_O_N_T_R_E_F_E_R_E_N_C_E__T_H_I_S__D_I_R_E_C_T_L_Y_L_O_L.validate!
120
+ C_O_N_F_I_G__D_O_N_T_R_E_F_E_R_E_N_C_E__T_H_I_S__D_I_R_E_C_T_L_Y_L_O_L
71
121
  end
72
122
 
73
123
  def self.config
74
- CONFIG.dup.freeze
124
+ C_O_N_F_I_G__D_O_N_T_R_E_F_E_R_E_N_C_E__T_H_I_S__D_I_R_E_C_T_L_Y_L_O_L.dup.freeze
75
125
  end
76
126
  end
77
127
  end
data/script/setup CHANGED
@@ -5,10 +5,5 @@ set -e
5
5
  bundle
6
6
 
7
7
  cd example/simple_app
8
- bundle
9
- bin/rake db:setup
10
- export PLAYWRIGHT_CLI_VERSION=$(bundle exec ruby -e 'require "playwright"; puts Playwright::COMPATIBLE_PLAYWRIGHT_VERSION.strip')
11
- PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 yarn add -D "playwright@$PLAYWRIGHT_CLI_VERSION"
12
- yarn run playwright install chromium
13
-
8
+ ./script/setup
14
9
  cd ../..
data/script/test CHANGED
@@ -7,7 +7,7 @@ bundle exec rake
7
7
 
8
8
  echo "-----> Testing example/simple_app"
9
9
  cd example/simple_app
10
- bin/rake
10
+ ./script/test
11
11
  cd ../..
12
12
 
13
13
  echo "-----> Looks good! 🪩"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searls-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
@@ -35,30 +35,52 @@ files:
35
35
  - README.md
36
36
  - Rakefile
37
37
  - app/controllers/searls/auth/base_controller.rb
38
+ - app/controllers/searls/auth/email_verifications_controller.rb
38
39
  - app/controllers/searls/auth/logins_controller.rb
39
40
  - app/controllers/searls/auth/registrations_controller.rb
41
+ - app/controllers/searls/auth/requests_password_resets_controller.rb
42
+ - app/controllers/searls/auth/resets_passwords_controller.rb
43
+ - app/controllers/searls/auth/settings_controller.rb
40
44
  - app/controllers/searls/auth/verifications_controller.rb
41
45
  - app/helpers/searls/auth/application_helper.rb
42
46
  - app/javascript/controllers/searls_auth_login_controller.js
43
47
  - app/javascript/controllers/searls_auth_otp_controller.js
44
48
  - app/mailers/searls/auth/base_mailer.rb
49
+ - app/mailers/searls/auth/email_verification_mailer.rb
45
50
  - app/mailers/searls/auth/login_link_mailer.rb
51
+ - app/mailers/searls/auth/password_reset_mailer.rb
52
+ - app/views/searls/auth/email_verification_mailer/verification_email.html.erb
53
+ - app/views/searls/auth/email_verification_mailer/verification_email.text.erb
46
54
  - app/views/searls/auth/layouts/mailer.html.erb
47
55
  - app/views/searls/auth/login_link_mailer/login_link.html.erb
48
56
  - app/views/searls/auth/login_link_mailer/login_link.text.erb
49
57
  - app/views/searls/auth/logins/show.html.erb
58
+ - app/views/searls/auth/password_reset_mailer/password_reset.html.erb
59
+ - app/views/searls/auth/password_reset_mailer/password_reset.text.erb
60
+ - app/views/searls/auth/registrations/pending_email_verification.html.erb
50
61
  - app/views/searls/auth/registrations/show.html.erb
62
+ - app/views/searls/auth/requests_password_resets/show.html.erb
63
+ - app/views/searls/auth/resets_passwords/show.html.erb
64
+ - app/views/searls/auth/settings/edit.html.erb
65
+ - app/views/searls/auth/shared/_login_fields.html.erb
66
+ - app/views/searls/auth/shared/_register_fields.html.erb
51
67
  - app/views/searls/auth/verifications/show.html.erb
52
68
  - config/importmap.rb
53
69
  - config/routes.rb
54
70
  - lib/searls/auth.rb
55
71
  - lib/searls/auth/authenticates_user.rb
72
+ - lib/searls/auth/builds_target_redirect_url.rb
56
73
  - lib/searls/auth/config.rb
57
74
  - lib/searls/auth/creates_user.rb
75
+ - lib/searls/auth/delivers_password_reset.rb
58
76
  - lib/searls/auth/emails_link.rb
77
+ - lib/searls/auth/emails_verification.rb
59
78
  - lib/searls/auth/engine.rb
79
+ - lib/searls/auth/parses_time_safely.rb
60
80
  - lib/searls/auth/railtie.rb
81
+ - lib/searls/auth/resets_password.rb
61
82
  - lib/searls/auth/resets_session.rb
83
+ - lib/searls/auth/updates_settings.rb
62
84
  - lib/searls/auth/version.rb
63
85
  - script/setup
64
86
  - script/setup_ci
@@ -84,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
106
  - !ruby/object:Gem::Version
85
107
  version: '0'
86
108
  requirements: []
87
- rubygems_version: 3.6.7
109
+ rubygems_version: 3.6.9
88
110
  specification_version: 4
89
111
  summary: Searls-flavored login for Rails apps
90
112
  test_files: []