rails_mvp_authentication 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/config/rails_mvp_authentication_manifest.js +1 -0
- data/app/assets/stylesheets/rails_mvp_authentication/application.css +15 -0
- data/app/controllers/rails_mvp_authentication/application_controller.rb +4 -0
- data/app/helpers/rails_mvp_authentication/application_helper.rb +4 -0
- data/app/jobs/rails_mvp_authentication/application_job.rb +4 -0
- data/app/mailers/rails_mvp_authentication/application_mailer.rb +6 -0
- data/app/models/rails_mvp_authentication/application_record.rb +5 -0
- data/app/views/layouts/rails_mvp_authentication/application.html.erb +15 -0
- data/config/routes.rb +2 -0
- data/lib/generators/rails_mvp_authentication/USAGE +5 -0
- data/lib/generators/rails_mvp_authentication/install_generator.rb +251 -0
- data/lib/generators/rails_mvp_authentication/templates/README +7 -0
- data/lib/generators/rails_mvp_authentication/templates/authentication.rb.tt +58 -0
- data/lib/generators/rails_mvp_authentication/templates/confirmations_controller.rb.tt +32 -0
- data/lib/generators/rails_mvp_authentication/templates/current.rb.tt +3 -0
- data/lib/generators/rails_mvp_authentication/templates/passwords_controller.rb.tt +52 -0
- data/lib/generators/rails_mvp_authentication/templates/sessions_controller.rb.tt +30 -0
- data/lib/generators/rails_mvp_authentication/templates/test/controllers/active_sessions_controller_test.rb.tt +68 -0
- data/lib/generators/rails_mvp_authentication/templates/test/controllers/confirmations_controller_test.rb.tt +143 -0
- data/lib/generators/rails_mvp_authentication/templates/test/controllers/passwords_controller_test.rb.tt +119 -0
- data/lib/generators/rails_mvp_authentication/templates/test/controllers/sessions_controller_test.rb.tt +105 -0
- data/lib/generators/rails_mvp_authentication/templates/test/controllers/users_controller_test.rb.tt +150 -0
- data/lib/generators/rails_mvp_authentication/templates/test/integration/friendly_redirects_test.rb.tt +23 -0
- data/lib/generators/rails_mvp_authentication/templates/test/integration/user_interface_test.rb.tt +35 -0
- data/lib/generators/rails_mvp_authentication/templates/test/mailers/previews/user_mailer_preview.rb.tt +17 -0
- data/lib/generators/rails_mvp_authentication/templates/test/mailers/user_mailer_test.rb.tt +25 -0
- data/lib/generators/rails_mvp_authentication/templates/test/models/active_session_test.rb.tt +18 -0
- data/lib/generators/rails_mvp_authentication/templates/test/models/user_test.rb.tt +183 -0
- data/lib/generators/rails_mvp_authentication/templates/test/system/logins_test.rb.tt +18 -0
- data/lib/generators/rails_mvp_authentication/templates/user.rb.tt +96 -0
- data/lib/generators/rails_mvp_authentication/templates/user_mailer.rb.tt +22 -0
- data/lib/generators/rails_mvp_authentication/templates/users_controller.rb.tt +59 -0
- data/lib/generators/rails_mvp_authentication/templates/views/confirmations/new.html.erb.tt +4 -0
- data/lib/generators/rails_mvp_authentication/templates/views/passwords/edit.html.erb.tt +11 -0
- data/lib/generators/rails_mvp_authentication/templates/views/passwords/new.html.erb.tt +4 -0
- data/lib/generators/rails_mvp_authentication/templates/views/sessions/new.html.erb.tt +15 -0
- data/lib/generators/rails_mvp_authentication/templates/views/user_mailer/confirmation.html.erb.tt +3 -0
- data/lib/generators/rails_mvp_authentication/templates/views/user_mailer/confirmation.text.erb.tt +3 -0
- data/lib/generators/rails_mvp_authentication/templates/views/user_mailer/password_reset.html.erb.tt +3 -0
- data/lib/generators/rails_mvp_authentication/templates/views/user_mailer/password_reset.text.erb.tt +3 -0
- data/lib/generators/rails_mvp_authentication/templates/views/users/edit.html.erb.tt +42 -0
- data/lib/generators/rails_mvp_authentication/templates/views/users/new.html.erb.tt +16 -0
- data/lib/rails_mvp_authentication/engine.rb +5 -0
- data/lib/rails_mvp_authentication/version.rb +3 -0
- data/lib/rails_mvp_authentication.rb +6 -0
- data/lib/tasks/rails_mvp_authentication_tasks.rake +4 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4fa3c307eee6e61d01e318fe1453a30660e18f0e2eb1de7b725c22f93c6a60e6
|
4
|
+
data.tar.gz: 8ac56c76c7dd2f316ef9b19c81e8c78987cade71cee289f2e1b3ef8c1dc22d0e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: da4f0c62616acff46d67f8ca95ae1b7606710a23e99dfab4b6225b24ab90dca5dab8aec39c64d5749d4b608a21a9ea6ed3891f7ecb5586c8b568b3d71f394bfc
|
7
|
+
data.tar.gz: c6a117f9c7f8cb7168087329e21a62636b2b8bb74561f28e77dcb5ce8052f5add760b3254f43dfd051cfd8198103f57703d364c547134edcb0d8706365db0c94
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Steve Polito
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# RailsMvpAuthentication
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "rails_mvp_authentication"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install rails_mvp_authentication
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/rails_mvp_authentication .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Rails mvp authentication</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= stylesheet_link_tag "rails_mvp_authentication/application", media: "all" %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
|
12
|
+
<%= yield %>
|
13
|
+
|
14
|
+
</body>
|
15
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
module RailsMvpAuthentication
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
desc "Rails authentication via a generator."
|
7
|
+
|
8
|
+
def perform
|
9
|
+
create_users_table
|
10
|
+
modify_users_table
|
11
|
+
create_user_model
|
12
|
+
add_bcrypt
|
13
|
+
add_routes
|
14
|
+
create_current_model
|
15
|
+
create_users_controller
|
16
|
+
create_user_views
|
17
|
+
create_confirmations_controller
|
18
|
+
create_confirmation_views
|
19
|
+
ceate_user_mailer
|
20
|
+
ceate_user_mailer_views
|
21
|
+
configure_hosts
|
22
|
+
create_authentication_concern
|
23
|
+
modify_application_controller
|
24
|
+
create_sessions_controller
|
25
|
+
create_session_views
|
26
|
+
create_passwords_controller
|
27
|
+
create_password_views
|
28
|
+
if using_default_test_suite
|
29
|
+
create_tests
|
30
|
+
modify_test_helper
|
31
|
+
end
|
32
|
+
add_links
|
33
|
+
print_instructions
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def add_bcrypt
|
39
|
+
return unless gemfile_exists
|
40
|
+
|
41
|
+
if bcrypt_is_commented_out
|
42
|
+
uncomment_lines(gemfile, /gem "bcrypt", "~> 3.1.7"/)
|
43
|
+
else
|
44
|
+
gem "bcrypt", "~> 3.1.7"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_links
|
49
|
+
inject_into_file "app/views/layouts/application.html.erb", after: "<body>\n" do
|
50
|
+
<<-ERB
|
51
|
+
<ul>
|
52
|
+
<% if user_signed_in? %>
|
53
|
+
<li><%= link_to "My Acount", account_path %></li>
|
54
|
+
<li><%= button_to "Logout", logout_path, method: :delete %></li>
|
55
|
+
<% else %>
|
56
|
+
<li><%= link_to "Login", login_path %></li>
|
57
|
+
<li><%= link_to "Sign Up", sign_up_path %></li>
|
58
|
+
<li><%= link_to "Forgot my password", new_password_path %></li>
|
59
|
+
<li><%= link_to "Didn't receive confirmation instructions", new_confirmation_path %></li>
|
60
|
+
<% end %>
|
61
|
+
</ul>
|
62
|
+
ERB
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_routes
|
67
|
+
route %(
|
68
|
+
post "sign_up", to: "users#create"
|
69
|
+
get "sign_up", to: "users#new"
|
70
|
+
put "account", to: "users#update"
|
71
|
+
get "account", to: "users#edit"
|
72
|
+
delete "account", to: "users#destroy"
|
73
|
+
resources :confirmations, only: [:create, :edit, :new], param: :confirmation_token
|
74
|
+
post "login", to: "sessions#create"
|
75
|
+
delete "logout", to: "sessions#destroy"
|
76
|
+
get "login", to: "sessions#new"
|
77
|
+
resources :passwords, only: [:create, :edit, :new, :update], param: :password_reset_token
|
78
|
+
resources :active_sessions, only: [:destroy] do
|
79
|
+
collection do
|
80
|
+
delete "destroy_all"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def bcrypt_is_commented_out
|
87
|
+
gemfile = path_to("Gemfile")
|
88
|
+
|
89
|
+
File.open(gemfile).each_line do |line|
|
90
|
+
return true if line == '# gem "bcrypt", "~> 3.1.7"'
|
91
|
+
end
|
92
|
+
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def configure_hosts
|
97
|
+
application(nil, env: "test") do
|
98
|
+
'config.action_mailer.default_url_options = {host: "example.com"}'
|
99
|
+
end
|
100
|
+
application(nil, env: "development") do
|
101
|
+
'config.action_mailer.default_url_options = {host: "localhost", port: 3000}'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_authentication_concern
|
106
|
+
template "authentication.rb", "app/controllers/concerns/authentication.rb"
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_confirmations_controller
|
110
|
+
template "confirmations_controller.rb", "app/controllers/confirmations_controller.rb"
|
111
|
+
end
|
112
|
+
|
113
|
+
def create_confirmation_views
|
114
|
+
template "views/confirmations/new.html.erb", "app/views/confirmations/new.html.erb"
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_current_model
|
118
|
+
template "current.rb", "app/models/current.rb"
|
119
|
+
end
|
120
|
+
|
121
|
+
def create_passwords_controller
|
122
|
+
template "passwords_controller.rb", "app/controllers/passwords_controller.rb"
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_password_views
|
126
|
+
template "views/passwords/new.html.erb", "app/views/passwords/new.html.erb"
|
127
|
+
template "views/passwords/edit.html.erb", "app/views/passwords/edit.html.erb"
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_sessions_controller
|
131
|
+
template "sessions_controller.rb", "app/controllers/sessions_controller.rb"
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_session_views
|
135
|
+
template "views/sessions/new.html.erb", "app/views/sessions/new.html.erb"
|
136
|
+
end
|
137
|
+
|
138
|
+
def create_users_controller
|
139
|
+
template "users_controller.rb", "app/controllers/users_controller.rb"
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_tests
|
143
|
+
template "test/controllers/active_sessions_controller_test.rb", "test/controllers/active_sessions_controller_test.rb"
|
144
|
+
template "test/controllers/confirmations_controller_test.rb", "test/controllers/confirmations_controller_test.rb"
|
145
|
+
template "test/controllers/active_sessions_controller_test.rb", "test/controllers/active_sessions_controller_test.rb"
|
146
|
+
template "test/controllers/passwords_controller_test.rb", "test/controllers/passwords_controller_test.rb"
|
147
|
+
template "test/controllers/sessions_controller_test.rb", "test/controllers/sessions_controller_test.rb"
|
148
|
+
template "test/controllers/users_controller_test.rb", "test/controllers/users_controller_test.rb"
|
149
|
+
|
150
|
+
template "test/integration/friendly_redirects_test.rb", "test/integration/friendly_redirects_test.rb"
|
151
|
+
template "test/integration/user_interface_test.rb", "test/integration/user_interface_test.rb"
|
152
|
+
|
153
|
+
template "test/mailers/previews/user_mailer_preview.rb", "test/mailers/previews/user_mailer_preview.rb"
|
154
|
+
template "test/mailers/user_mailer_test.rb", "test/mailers/user_mailer_test.rb"
|
155
|
+
|
156
|
+
template "test/models/user_test.rb", "test/models/user_test.rb"
|
157
|
+
template "test/models/active_session_test.rb", "test/models/active_session_test.rb"
|
158
|
+
|
159
|
+
template "test/system/logins_test.rb", "test/system/logins_test.rb"
|
160
|
+
end
|
161
|
+
|
162
|
+
def ceate_user_mailer
|
163
|
+
template "user_mailer.rb", "app/mailers/user_mailer.rb"
|
164
|
+
end
|
165
|
+
|
166
|
+
def ceate_user_mailer_views
|
167
|
+
template "views/user_mailer/confirmation.html.erb", "app/views/user_mailer/confirmation.html.erb"
|
168
|
+
template "views/user_mailer/confirmation.text.erb", "app/views/user_mailer/confirmation.text.erb"
|
169
|
+
template "views/user_mailer/password_reset.html.erb", "app/views/user_mailer/password_reset.html.erb"
|
170
|
+
template "views/user_mailer/password_reset.text.erb", "app/views/user_mailer/password_reset.text.erb"
|
171
|
+
end
|
172
|
+
|
173
|
+
def create_user_model
|
174
|
+
template "user.rb", "app/models/user.rb"
|
175
|
+
end
|
176
|
+
|
177
|
+
def create_users_table
|
178
|
+
generate "migration", "create_users_table email:string:index confirmed_at:datetime password_digest:string unconfirmed_email:string"
|
179
|
+
end
|
180
|
+
|
181
|
+
def create_user_views
|
182
|
+
template "views/users/edit.html.erb", "app/views/users/edit.html.erb"
|
183
|
+
template "views/users/new.html.erb", "app/views/users/new.html.erb"
|
184
|
+
end
|
185
|
+
|
186
|
+
def directory_exists(directory)
|
187
|
+
File.directory?(directory)
|
188
|
+
end
|
189
|
+
|
190
|
+
def gemfile
|
191
|
+
path_to("Gemfile")
|
192
|
+
end
|
193
|
+
|
194
|
+
def gemfile_exists
|
195
|
+
File.exist?(gemfile)
|
196
|
+
end
|
197
|
+
|
198
|
+
def modify_application_controller
|
199
|
+
inject_into_file "app/controllers/application_controller.rb", "\tinclude Authentication\n", after: "class ApplicationController < ActionController::Base\n"
|
200
|
+
end
|
201
|
+
|
202
|
+
def modify_test_helper
|
203
|
+
inject_into_class "test/test_helper.rb", "ActiveSupport::TestCase" do
|
204
|
+
<<-RUBY
|
205
|
+
def current_user
|
206
|
+
if session[:current_active_session_id].present?
|
207
|
+
ActiveSession.find_by(id: session[:current_active_session_id])&.user
|
208
|
+
else
|
209
|
+
cookies[:remember_token].present?
|
210
|
+
ActiveSession.find_by(remember_token: cookies[:remember_token])&.user
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def login(user, remember_user: nil)
|
215
|
+
post login_path, params: {
|
216
|
+
user: {
|
217
|
+
email: user.email,
|
218
|
+
password: user.password,
|
219
|
+
remember_me: remember_user == true ? 1 : 0
|
220
|
+
}
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
def logout
|
225
|
+
session.delete(:current_active_session_id)
|
226
|
+
end
|
227
|
+
RUBY
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def modify_users_table
|
232
|
+
migration = Dir.glob(Rails.root.join("db/migrate/*")).max_by { |f| File.mtime(f) }
|
233
|
+
gsub_file migration, /t.string :email/, "t.string :email, null: false"
|
234
|
+
gsub_file migration, /t.string :password_digest/, "t.string :password_digest, null: false"
|
235
|
+
gsub_file migration, /add_index :users_tables, :email/, "add_index :users_tables, :email, unique: true"
|
236
|
+
end
|
237
|
+
|
238
|
+
def path_to(path)
|
239
|
+
Rails.root.join(path)
|
240
|
+
end
|
241
|
+
|
242
|
+
def print_instructions
|
243
|
+
readme "README"
|
244
|
+
end
|
245
|
+
|
246
|
+
def using_default_test_suite
|
247
|
+
directory_exists(path_to("test"))
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Authentication
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
before_action :current_user
|
6
|
+
helper_method :current_user
|
7
|
+
helper_method :user_signed_in?
|
8
|
+
end
|
9
|
+
|
10
|
+
def authenticate_user!
|
11
|
+
store_location
|
12
|
+
redirect_to login_path, alert: "You need to login to access that page." unless user_signed_in?
|
13
|
+
end
|
14
|
+
|
15
|
+
def login(user)
|
16
|
+
reset_session
|
17
|
+
active_session = user.active_sessions.create!(user_agent: request.user_agent, ip_address: request.ip)
|
18
|
+
session[:current_active_session_id] = active_session.id
|
19
|
+
|
20
|
+
active_session
|
21
|
+
end
|
22
|
+
|
23
|
+
def forget_active_session
|
24
|
+
cookies.delete :remember_token
|
25
|
+
end
|
26
|
+
|
27
|
+
def logout
|
28
|
+
active_session = ActiveSession.find_by(id: session[:current_active_session_id])
|
29
|
+
reset_session
|
30
|
+
active_session.destroy! if active_session.present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def redirect_if_authenticated
|
34
|
+
redirect_to root_path, alert: "You are already logged in." if user_signed_in?
|
35
|
+
end
|
36
|
+
|
37
|
+
def remember(active_session)
|
38
|
+
cookies.permanent.encrypted[:remember_token] = active_session.remember_token
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def current_user
|
44
|
+
Current.user = if session[:current_active_session_id].present?
|
45
|
+
ActiveSession.find_by(id: session[:current_active_session_id])&.user
|
46
|
+
elsif cookies.permanent.encrypted[:remember_token].present?
|
47
|
+
ActiveSession.find_by(remember_token: cookies.permanent.encrypted[:remember_token])&.user
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def user_signed_in?
|
52
|
+
Current.user.present?
|
53
|
+
end
|
54
|
+
|
55
|
+
def store_location
|
56
|
+
session[:user_return_to] = request.original_url if request.get? && request.local?
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class ConfirmationsController < ApplicationController
|
2
|
+
before_action :redirect_if_authenticated, only: [:create, :new]
|
3
|
+
|
4
|
+
def create
|
5
|
+
@user = User.find_by(email: params[:user][:email].downcase)
|
6
|
+
|
7
|
+
if @user.present? && @user.unconfirmed?
|
8
|
+
@user.send_confirmation_email!
|
9
|
+
redirect_to root_path, notice: "Check your email for confirmation instructions."
|
10
|
+
else
|
11
|
+
redirect_to new_confirmation_path, alert: "We could not find a user with that email or that email has already been confirmed."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
@user = User.find_signed(params[:confirmation_token], purpose: :confirm_email)
|
17
|
+
if @user.present? && @user.unconfirmed_or_reconfirming?
|
18
|
+
if @user.confirm!
|
19
|
+
login @user
|
20
|
+
redirect_to root_path, notice: "Your account has been confirmed."
|
21
|
+
else
|
22
|
+
redirect_to new_confirmation_path, alert: "Something went wrong."
|
23
|
+
end
|
24
|
+
else
|
25
|
+
redirect_to new_confirmation_path, alert: "Invalid token."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def new
|
30
|
+
@user = User.new
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class PasswordsController < ApplicationController
|
2
|
+
before_action :redirect_if_authenticated
|
3
|
+
|
4
|
+
def create
|
5
|
+
@user = User.find_by(email: params[:user][:email].downcase)
|
6
|
+
if @user.present?
|
7
|
+
if @user.confirmed?
|
8
|
+
@user.send_password_reset_email!
|
9
|
+
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
10
|
+
else
|
11
|
+
redirect_to new_confirmation_path, alert: "Please confirm your email first."
|
12
|
+
end
|
13
|
+
else
|
14
|
+
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit
|
19
|
+
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
20
|
+
if @user.present? && @user.unconfirmed?
|
21
|
+
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
22
|
+
elsif @user.nil?
|
23
|
+
redirect_to new_password_path, alert: "Invalid or expired token."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def new
|
28
|
+
end
|
29
|
+
|
30
|
+
def update
|
31
|
+
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
32
|
+
if @user
|
33
|
+
if @user.unconfirmed?
|
34
|
+
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
35
|
+
elsif @user.update(password_params)
|
36
|
+
redirect_to login_path, notice: "Sign in."
|
37
|
+
else
|
38
|
+
flash.now[:alert] = @user.errors.full_messages.to_sentence
|
39
|
+
render :edit, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
else
|
42
|
+
flash.now[:alert] = "Invalid or expired token."
|
43
|
+
render :new, status: :unprocessable_entity
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def password_params
|
50
|
+
params.require(:user).permit(:password, :password_confirmation)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class SessionsController < ApplicationController
|
2
|
+
before_action :redirect_if_authenticated, only: [:create, :new]
|
3
|
+
before_action :authenticate_user!, only: [:destroy]
|
4
|
+
|
5
|
+
def create
|
6
|
+
@user = User.authenticate_by(email: params[:user][:email].downcase, password: params[:user][:password])
|
7
|
+
if @user
|
8
|
+
if @user.unconfirmed?
|
9
|
+
redirect_to new_confirmation_path, alert: "Incorrect email or password."
|
10
|
+
else
|
11
|
+
after_login_path = session[:user_return_to] || root_path
|
12
|
+
active_session = login @user
|
13
|
+
remember(active_session) if params[:user][:remember_me] == "1"
|
14
|
+
redirect_to after_login_path, notice: "Signed in."
|
15
|
+
end
|
16
|
+
else
|
17
|
+
flash.now[:alert] = "Incorrect email or password."
|
18
|
+
render :new, status: :unprocessable_entity
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy
|
23
|
+
forget_active_session
|
24
|
+
logout
|
25
|
+
redirect_to root_path, notice: "Signed out."
|
26
|
+
end
|
27
|
+
|
28
|
+
def new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ActiveSessionsControllerTest < ActionDispatch::IntegrationTest
|
4
|
+
setup do
|
5
|
+
@confirmed_user = User.create!(email: "confirmed_user@example.com", password: "password", password_confirmation: "password", confirmed_at: Time.current)
|
6
|
+
end
|
7
|
+
|
8
|
+
test "should destroy all active sessions" do
|
9
|
+
login @confirmed_user
|
10
|
+
@confirmed_user.active_sessions.create!
|
11
|
+
|
12
|
+
assert_difference("ActiveSession.count", -2) do
|
13
|
+
delete destroy_all_active_sessions_path
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_redirected_to root_path
|
17
|
+
assert_nil current_user
|
18
|
+
assert_not_nil flash[:notice]
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should destroy all active sessions and forget active sessions" do
|
22
|
+
login @confirmed_user, remember_user: true
|
23
|
+
@confirmed_user.active_sessions.create!
|
24
|
+
|
25
|
+
assert_difference("ActiveSession.count", -2) do
|
26
|
+
delete destroy_all_active_sessions_path
|
27
|
+
end
|
28
|
+
|
29
|
+
assert_nil current_user
|
30
|
+
assert cookies[:remember_token].blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
test "should destroy another session" do
|
34
|
+
login @confirmed_user
|
35
|
+
@confirmed_user.active_sessions.create!
|
36
|
+
|
37
|
+
assert_difference("ActiveSession.count", -1) do
|
38
|
+
delete active_session_path(@confirmed_user.active_sessions.last)
|
39
|
+
end
|
40
|
+
|
41
|
+
assert_redirected_to account_path
|
42
|
+
assert_not_nil current_user
|
43
|
+
assert_not_nil flash[:notice]
|
44
|
+
end
|
45
|
+
|
46
|
+
test "should destroy current session" do
|
47
|
+
login @confirmed_user
|
48
|
+
|
49
|
+
assert_difference("ActiveSession.count", -1) do
|
50
|
+
delete active_session_path(@confirmed_user.active_sessions.last)
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_redirected_to root_path
|
54
|
+
assert_nil current_user
|
55
|
+
assert_not_nil flash[:notice]
|
56
|
+
end
|
57
|
+
|
58
|
+
test "should destroy current session and forget current active session" do
|
59
|
+
login @confirmed_user, remember_user: true
|
60
|
+
|
61
|
+
assert_difference("ActiveSession.count", -1) do
|
62
|
+
delete active_session_path(@confirmed_user.active_sessions.last)
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_nil current_user
|
66
|
+
assert cookies[:remember_token].blank?
|
67
|
+
end
|
68
|
+
end
|