orthodox 0.2.4 → 0.3.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/lib/generators/authentication/USAGE +14 -0
- data/lib/generators/authentication/authentication_generator.rb +214 -0
- data/lib/generators/authentication/templates/controllers/concerns/authentication.rb.erb +110 -0
- data/lib/generators/authentication/templates/controllers/concerns/two_factor_authentication.rb +40 -0
- data/lib/generators/authentication/templates/controllers/password_resets_controller.rb.erb +54 -0
- data/lib/generators/authentication/templates/controllers/sessions_controller.rb.erb +36 -0
- data/lib/generators/authentication/templates/controllers/tfa_sessions_controller.rb.erb +48 -0
- data/lib/generators/authentication/templates/controllers/tfas_controller.rb.erb +38 -0
- data/lib/generators/authentication/templates/helpers/otp_credentials_helper.rb +33 -0
- data/lib/generators/authentication/templates/javascript/tfa_forms.js +19 -0
- data/lib/generators/authentication/templates/models/concerns/authenticateable.rb +37 -0
- data/lib/generators/authentication/templates/models/concerns/otpable.rb +26 -0
- data/lib/generators/authentication/templates/models/concerns/password_resetable.rb +19 -0
- data/lib/generators/authentication/templates/models/otp_credential.rb.erb +133 -0
- data/lib/generators/authentication/templates/models/password_reset_token.rb +64 -0
- data/lib/generators/authentication/templates/models/session.rb.erb +80 -0
- data/lib/generators/authentication/templates/models/tfa_session.rb +77 -0
- data/lib/generators/authentication/templates/spec/models/otp_credential_spec.rb +215 -0
- data/lib/generators/authentication/templates/spec/models/password_reset_token_spec.rb +146 -0
- data/lib/generators/authentication/templates/spec/models/session_spec.rb.erb +45 -0
- data/lib/generators/authentication/templates/spec/models/tfa_session_spec.rb.erb +115 -0
- data/lib/generators/authentication/templates/spec/support/authentication_helpers.rb +18 -0
- data/lib/generators/authentication/templates/spec/support/factory_bot.rb +5 -0
- data/lib/generators/authentication/templates/spec/system/authentication_spec.rb.erb +25 -0
- data/lib/generators/authentication/templates/spec/system/password_resets_spec.rb.erb +73 -0
- data/lib/generators/authentication/templates/spec/system/tfa_authentication_spec.rb.erb +38 -0
- data/lib/generators/authentication/templates/views/mailers/password_reset_link.html.slim.erb +7 -0
- data/lib/generators/authentication/templates/views/password_resets/edit.html.slim.erb +16 -0
- data/lib/generators/authentication/templates/views/password_resets/new.html.slim.erb +12 -0
- data/lib/generators/authentication/templates/views/sessions/new.html.slim.erb +21 -0
- data/lib/generators/authentication/templates/views/tfa_sessions/new.html.slim.erb +26 -0
- data/lib/generators/authentication/templates/views/tfas/show.html.slim.erb +9 -0
- data/lib/generators/base_controller/USAGE +8 -0
- data/lib/generators/base_controller/base_controller_generator.rb +22 -0
- data/lib/generators/base_controller/templates/base_controller.rb.erb +7 -0
- data/lib/generators/layout_helper/USAGE +8 -0
- data/lib/generators/layout_helper/layout_helper_generator.rb +55 -0
- data/lib/orthodox/version.rb +1 -1
- metadata +39 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 616ba8695069097dae8c09c0912d366b2491ea1747d683e91fce2ee86bc91456
|
4
|
+
data.tar.gz: 05b4176b9a0c81b779ab5ac0490e21437eb3eaec6daad9fa98ce503de0481b4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 436f151edd60aa7a0b8437aa7652d4406f95a78ae9d26aa4b05e0dd5948c86c71baf08225a58162cd50039e62688594ea8a57e433eef4b4459dea42f6b3de0a6
|
7
|
+
data.tar.gz: da50fc10b1b96d2a1f6b34d5ae13a57b5c9aa25b2cef9c8f9a8e719d7afa4d25595d6261493c913732fd8da36bc7f546cf9791fffe7a1080943ca975b1d361db
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
Adds boilerplate controllers, models, and views for authenticating a model.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate authentication Member
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/models/concerns/authenticateable.rb
|
9
|
+
app/controllers/concerns/authentication.rb
|
10
|
+
app/controllers/members/sessions_controller.rb
|
11
|
+
app/models/member_session.rb
|
12
|
+
app/views/members/sessions/new.html.slim
|
13
|
+
spec/system/members/authentication_spec.rb
|
14
|
+
spec/models/member_session_spec.rb
|
@@ -0,0 +1,214 @@
|
|
1
|
+
class AuthenticationGenerator < Rails::Generators::NamedBase
|
2
|
+
source_root File.expand_path('templates', __dir__)
|
3
|
+
|
4
|
+
desc "Creates authentication views, controllers and models for a given Model"
|
5
|
+
|
6
|
+
class_option :skip_views, type: :boolean, default: false
|
7
|
+
|
8
|
+
class_option :skip_tests, type: :boolean, default: false
|
9
|
+
|
10
|
+
class_option :two_factor, type: :boolean, default: false
|
11
|
+
|
12
|
+
def create_controllers
|
13
|
+
generate "base_controller", class_name
|
14
|
+
template "controllers/sessions_controller.rb.erb",
|
15
|
+
"app/controllers/#{plural_file_name}/sessions_controller.rb"
|
16
|
+
template "controllers/password_resets_controller.rb.erb",
|
17
|
+
"app/controllers/#{plural_file_name}/password_resets_controller.rb"
|
18
|
+
|
19
|
+
if options[:two_factor]
|
20
|
+
template "controllers/tfa_sessions_controller.rb.erb",
|
21
|
+
"app/controllers/#{plural_file_name}/tfa_sessions_controller.rb"
|
22
|
+
|
23
|
+
template "controllers/tfas_controller.rb.erb",
|
24
|
+
"app/controllers/#{plural_file_name}/tfas_controller.rb"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def extend_controllers
|
29
|
+
inject_into_class "app/controllers/#{plural_name}/base_controller.rb",
|
30
|
+
"#{plural_class_name}::BaseController",
|
31
|
+
" authenticate_model :#{singular_name}, tfa: #{options[:two_factor]}\n"
|
32
|
+
include_module_in_controller("#{plural_name}/base_controller", "Authentication")
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def ensure_helpers
|
37
|
+
if options[:two_factor]
|
38
|
+
copy_file "helpers/otp_credentials_helper.rb", "app/helpers/otp_credentials_helper.rb"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def ensure_js
|
43
|
+
if options[:two_factor]
|
44
|
+
copy_file "javascript/tfa_forms.js", "app/javascript/packs/tfa_forms.js"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_mailer
|
49
|
+
generate "mailer", "#{class_name}Mailer"
|
50
|
+
inject_into_class "app/mailers/#{singular_name}_mailer.rb", "#{class_name}Mailer", <<~RUBY
|
51
|
+
|
52
|
+
def password_reset_link(#{singular_name})
|
53
|
+
@#{singular_name} = #{singular_name}
|
54
|
+
mail(to: #{singular_name}.email, subject: "Reset your password")
|
55
|
+
end
|
56
|
+
|
57
|
+
RUBY
|
58
|
+
template "views/mailers/password_reset_link.html.slim.erb",
|
59
|
+
"app/views/#{singular_name}_mailer/password_reset_link.html.slim"
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_models
|
63
|
+
copy_file "models/password_reset_token.rb", "app/models/password_reset_token.rb"
|
64
|
+
if options[:two_factor]
|
65
|
+
template "models/otp_credential.rb.erb", "app/models/otp_credential.rb"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def extend_models
|
70
|
+
include_module_in_model(class_name, "Authenticateable")
|
71
|
+
include_module_in_model(class_name, "PasswordResetable")
|
72
|
+
if options[:two_factor]
|
73
|
+
include_module_in_model(class_name, "Otpable")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_form_objects
|
78
|
+
template "models/session.rb.erb", "app/models/#{singular_name}_session.rb"
|
79
|
+
if options[:two_factor]
|
80
|
+
copy_file "models/tfa_session.rb", "app/models/tfa_session.rb"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def ensure_concerns
|
85
|
+
template "controllers/concerns/authentication.rb.erb",
|
86
|
+
"app/controllers/concerns/authentication.rb"
|
87
|
+
copy_file "models/concerns/authenticateable.rb",
|
88
|
+
"app/models/concerns/authenticateable.rb"
|
89
|
+
copy_file "models/concerns/password_resetable.rb",
|
90
|
+
"app/models/concerns/password_resetable.rb"
|
91
|
+
|
92
|
+
if options[:two_factor]
|
93
|
+
copy_file "controllers/concerns/two_factor_authentication.rb",
|
94
|
+
"app/controllers/concerns/two_factor_authentication.rb"
|
95
|
+
|
96
|
+
copy_file "models/concerns/otpable.rb", "app/models/concerns/otpable.rb"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_migrations
|
101
|
+
generate "migration", "create_password_reset_tokens secret:token "\
|
102
|
+
"expires_at:datetime:index "\
|
103
|
+
"resetable:references{polymorphic}"
|
104
|
+
if options[:two_factor]
|
105
|
+
generate "migration", "create_otp_credentials \
|
106
|
+
created_at:datetime \
|
107
|
+
last_used_at:datetime \
|
108
|
+
secret:string{32} \
|
109
|
+
authable:references{polymorphic} \
|
110
|
+
recovery_codes:json"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_view_templates
|
115
|
+
return if options[:skip_views]
|
116
|
+
template "views/sessions/new.html.slim.erb",
|
117
|
+
"app/views/#{plural_name}/sessions/new.html.slim"
|
118
|
+
|
119
|
+
template "views/password_resets/new.html.slim.erb",
|
120
|
+
"app/views/#{plural_name}/password_resets/new.html.slim"
|
121
|
+
|
122
|
+
template "views/password_resets/edit.html.slim.erb",
|
123
|
+
"app/views/#{plural_name}/password_resets/edit.html.slim"
|
124
|
+
|
125
|
+
if options[:two_factor]
|
126
|
+
template "views/tfa_sessions/new.html.slim.erb",
|
127
|
+
"app/views/#{plural_name}/tfa_sessions/new.html.slim"
|
128
|
+
template "views/tfas/show.html.slim.erb",
|
129
|
+
"app/views/#{plural_name}/tfas/show.html.slim"
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_specs
|
135
|
+
return if options[:skip_tests]
|
136
|
+
|
137
|
+
copy_file "spec/support/factory_bot.rb", "spec/support/factory_bot.rb"
|
138
|
+
|
139
|
+
template "spec/system/authentication_spec.rb.erb",
|
140
|
+
"spec/system/#{plural_name}/authentication_spec.rb"
|
141
|
+
|
142
|
+
template "spec/system/password_resets_spec.rb.erb",
|
143
|
+
"spec/system/#{plural_name}/password_resets_spec.rb"
|
144
|
+
|
145
|
+
template "spec/models/session_spec.rb.erb",
|
146
|
+
"spec/models/#{singular_name}_session_spec.rb"
|
147
|
+
|
148
|
+
copy_file "spec/models/password_reset_token_spec.rb",
|
149
|
+
"spec/models/password_reset_token_spec.rb"
|
150
|
+
|
151
|
+
if options[:two_factor]
|
152
|
+
copy_file "spec/support/authentication_helpers.rb",
|
153
|
+
"spec/support/authentication_helpers.rb"
|
154
|
+
template "spec/models/tfa_session_spec.rb.erb", "spec/models/tfa_session_spec.rb"
|
155
|
+
copy_file "spec/models/otp_credential_spec.rb",
|
156
|
+
"spec/models/otp_credential_spec.rb"
|
157
|
+
template "spec/system/tfa_authentication_spec.rb.erb",
|
158
|
+
"spec/system/#{plural_name}/tfa_authentication_spec.rb"
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def create_factories
|
164
|
+
generate "factory_bot:model", "otp_credential"
|
165
|
+
generate "factory_bot:model", "password_reset_token"
|
166
|
+
generate "factory_bot:model", "#{singular_name}_session email:email password:password"
|
167
|
+
end
|
168
|
+
|
169
|
+
def ensure_gems
|
170
|
+
gem "validates_email_format_of", version: "~> 1.6"
|
171
|
+
gem "slim-rails"
|
172
|
+
gem "factory_bot_rails"
|
173
|
+
gem "faker"
|
174
|
+
if options[:two_factor]
|
175
|
+
gem "rotp", version: "~> 5.1.0"
|
176
|
+
gem "rqrcode", require: false
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_routes
|
181
|
+
route <<~RUBY
|
182
|
+
namespace :#{plural_name} do
|
183
|
+
|
184
|
+
resource :session, only: [:new, :create, :destroy]
|
185
|
+
|
186
|
+
#{"resource :tfa_session, only: [:new, :create]" if options[:two_factor]}
|
187
|
+
|
188
|
+
resource :tfa, only: [:create, :show, :destroy]
|
189
|
+
|
190
|
+
resources :password_resets, only: [:new, :create, :edit, :update], param: :token
|
191
|
+
|
192
|
+
end
|
193
|
+
RUBY
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def plural_class_name
|
199
|
+
class_name.pluralize
|
200
|
+
end
|
201
|
+
|
202
|
+
def include_module_in_controller(controller_name, module_name)
|
203
|
+
class_name = controller_name.classify
|
204
|
+
inject_into_class "app/controllers/#{controller_name}.rb", class_name,
|
205
|
+
" include #{module_name}\n"
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
def include_module_in_model(model_name, module_name)
|
210
|
+
inject_into_class "app/models/#{model_name.underscore}.rb", model_name,
|
211
|
+
" include #{module_name}\n"
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal
|
2
|
+
|
3
|
+
# Concern added to controllres to provide methods for authentication.
|
4
|
+
#
|
5
|
+
# Automatically generated by the orthodox gem (https://github.com/katanacode/orthodox)
|
6
|
+
# (c) Copyright 2019 Katana Code Ltd. All Rights Reserved.
|
7
|
+
module Authentication
|
8
|
+
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Sign in a given record as a given type
|
14
|
+
#
|
15
|
+
# record - An AppliationRecord subclass instance (e.g. A Member)
|
16
|
+
# as - A String or Symbol with the model name (e.g. "member")
|
17
|
+
<%- if options[:two_factor] -%>
|
18
|
+
# tfa - Mark as Two-Factor authentication authenticated.
|
19
|
+
<%- end -%>
|
20
|
+
#
|
21
|
+
# Returns Integer
|
22
|
+
def sign_in(record, as:<%= ", tfa: false" if options[:two_factor] -%>)
|
23
|
+
session[:"#{as}_id"] = record.id.to_i
|
24
|
+
<%- if options[:two_factor] -%>
|
25
|
+
session[:"#{as}_tfa_authenticated"] = tfa
|
26
|
+
<%- end -%>
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sign out a given record type.
|
30
|
+
#
|
31
|
+
# as - A String or Symbol with the model name (e.g. "member")
|
32
|
+
def sign_out(as)
|
33
|
+
session[:"#{as}_id"] = nil
|
34
|
+
<%- if options[:two_factor] -%>
|
35
|
+
session[:"#{as}_tfa_authenticated"] = nil
|
36
|
+
<%- end -%>
|
37
|
+
instance_variable_set("@current_#{as}", nil)
|
38
|
+
end
|
39
|
+
|
40
|
+
module ClassMethods
|
41
|
+
|
42
|
+
# Create a bunch of authentication methods for a given ActiveRecord model
|
43
|
+
def authenticate_model(model_name, **options)
|
44
|
+
# Define a current_<model> method to load the currently signed in record, if present
|
45
|
+
#
|
46
|
+
# Returns ApplicationRecord subclass
|
47
|
+
define_method(:"current_#{model_name}") do
|
48
|
+
instance_method_name = "@current_#{model_name}"
|
49
|
+
if instance_variable_get(instance_method_name).present?
|
50
|
+
instance_variable_get(instance_method_name)
|
51
|
+
else
|
52
|
+
scope = send(:"#{model_name}_auth_scope")
|
53
|
+
instance_variable_set(instance_method_name,
|
54
|
+
scope.find_by(id: session[:"#{model_name}_id"]))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Define a controller before_action method to authenticate a record for the given
|
59
|
+
# model. Redirects to the <model_name>_failed_authentication_url if not passed.
|
60
|
+
#
|
61
|
+
# Returns nil
|
62
|
+
define_method(:"authenticate_#{model_name}") do
|
63
|
+
unless send(:"current_#{model_name}?")
|
64
|
+
redirect_to send(:"#{model_name}_failed_authentication_url"),
|
65
|
+
warn: "You must be signed in to do that"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
before_action :"authenticate_#{model_name}"
|
70
|
+
|
71
|
+
# Creates a scope that records are loaded through when being authenticated. Subclass
|
72
|
+
# this method to customise the load conditions.
|
73
|
+
#
|
74
|
+
# Returns ActiveRecord::Relation
|
75
|
+
define_method(:"#{model_name}_auth_scope") do
|
76
|
+
model_name.to_s.classify.constantize.all
|
77
|
+
end
|
78
|
+
|
79
|
+
# Creates a boolean method to check if a current_<model_name> has been authenticated
|
80
|
+
# or not.
|
81
|
+
#
|
82
|
+
# Returns Boolean
|
83
|
+
define_method(:"current_#{model_name}?") { send(:"current_#{model_name}").present? }
|
84
|
+
|
85
|
+
alias_method :"#{model_name}_signed_in?", :"current_#{model_name}?"
|
86
|
+
|
87
|
+
alias_method :"#{model_name}_failed_authentication_url",
|
88
|
+
:"new_#{model_name.to_s.pluralize}_session_url"
|
89
|
+
|
90
|
+
helper_method :"current_#{model_name}"
|
91
|
+
helper_method :"current_#{model_name}?"
|
92
|
+
helper_method :"#{model_name}_signed_in?"
|
93
|
+
|
94
|
+
private :"current_#{model_name}"
|
95
|
+
private :"current_#{model_name}?"
|
96
|
+
private :"#{model_name}_signed_in?"
|
97
|
+
private :"authenticate_#{model_name}"
|
98
|
+
|
99
|
+
<%- if options[:two_factor] -%>
|
100
|
+
# This is included if the authentication generator is run with --two-factor=true
|
101
|
+
if options[:tfa] == true
|
102
|
+
include TwoFactorAuthentication
|
103
|
+
define_tfa_methods(model_name)
|
104
|
+
end
|
105
|
+
<%- end -%>
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
data/lib/generators/authentication/templates/controllers/concerns/two_factor_authentication.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module TwoFactorAuthentication
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def define_tfa_methods(model_name)
|
11
|
+
define_method :"authenticate_#{model_name}_with_tfa" do
|
12
|
+
|
13
|
+
send(:"authenticate_#{model_name}_without_tfa")
|
14
|
+
|
15
|
+
record = send(:"current_#{model_name}")
|
16
|
+
return unless record
|
17
|
+
if record.tfa? && !send(:"current_#{model_name}_tfa_authenticated?")
|
18
|
+
redirect_to send(:"new_#{model_name.to_s.pluralize}_tfa_session_url"),
|
19
|
+
warn: "You cannot proceed without authenticating"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method :"current_#{model_name}_tfa_authenticated?" do
|
25
|
+
session[:"#{model_name}_tfa_authenticated"] == true
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method :"#{model_name}_tfa_success_redirect_url" do
|
29
|
+
send(:"#{model_name.to_s.pluralize}_dashboard_url")
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :"authenticate_#{model_name}_without_tfa", :"authenticate_#{model_name}"
|
33
|
+
|
34
|
+
alias_method :"authenticate_#{model_name}", :"authenticate_#{model_name}_with_tfa"
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal
|
2
|
+
class <%= plural_class_name %>::PasswordResetsController < <%= plural_class_name %>::BaseController
|
3
|
+
|
4
|
+
skip_before_action :authenticate_<%= singular_name %>
|
5
|
+
|
6
|
+
def new
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
@<%= singular_name %> = <%= plural_name %>_scope.find_by(email: permitted_params[:email])
|
11
|
+
if @<%= singular_name %>
|
12
|
+
@<%= singular_name %>.create_password_reset_token
|
13
|
+
<%= class_name %>Mailer.password_reset_link(@<%= singular_name %>).deliver_later
|
14
|
+
end
|
15
|
+
redirect_to new_<%= plural_name %>_session_url,
|
16
|
+
notice: "Please check your email for a password reset link"
|
17
|
+
end
|
18
|
+
|
19
|
+
def edit
|
20
|
+
@<%= singular_name %> = find_<%= singular_name %>_from_token(params[:token])
|
21
|
+
if @<%= singular_name %>.nil? or @<%= singular_name %>.password_reset_token.expired?
|
22
|
+
redirect_to new_<%= plural_name %>_session_url,
|
23
|
+
error: "The link you followed does not look valid"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
@<%= singular_name %> = find_<%= singular_name %>_from_token(params[:token])
|
29
|
+
if @<%= singular_name %>.update(password: permitted_params[:password],
|
30
|
+
password_confirmation: permitted_params[:password_confirmation])
|
31
|
+
@<%= singular_name %>.destroy_password_reset_token
|
32
|
+
redirect_to new_<%= plural_name %>_session_url, notice: "Successfully reset your password"
|
33
|
+
else
|
34
|
+
render :edit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def permitted_params
|
41
|
+
params.require(:<%= singular_name %>).permit(:email, :password, :password_confirmation)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Change me to suit the scoping requirements for this project
|
45
|
+
def <%= plural_name %>_scope
|
46
|
+
<%= class_name %>.all
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_<%= singular_name %>_from_token(token)
|
50
|
+
<%= plural_name %>_scope.joins(:password_reset_token)
|
51
|
+
.where(password_reset_tokens: { secret: params[:token] }).first
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|