authentication-zero 1.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +9 -7
  4. data/lib/authentication_zero/version.rb +1 -1
  5. data/lib/generators/authentication/authentication_generator.rb +17 -10
  6. data/lib/generators/authentication/templates/controllers/api/password_resets_controller.rb.tt +2 -6
  7. data/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt +26 -4
  8. data/lib/generators/authentication/templates/controllers/html/cancellations_controller.rb.tt +1 -1
  9. data/lib/generators/authentication/templates/controllers/html/emails_controller.rb.tt +1 -1
  10. data/lib/generators/authentication/templates/controllers/html/password_resets_controller.rb.tt +2 -2
  11. data/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt +1 -1
  12. data/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt +1 -2
  13. data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +21 -9
  14. data/lib/generators/authentication/templates/erb/password_resets/new.html.erb.tt +1 -1
  15. data/lib/generators/authentication/templates/erb/session_mailer/signed_in.html.erb.tt +21 -0
  16. data/lib/generators/authentication/templates/erb/session_mailer/signed_in.text.erb.tt +17 -0
  17. data/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt +34 -0
  18. data/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +0 -5
  19. data/lib/generators/authentication/templates/mailers/password_mailer.rb.tt +1 -5
  20. data/lib/generators/authentication/templates/mailers/session_mailer.rb.tt +6 -0
  21. data/lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt +11 -0
  22. data/lib/generators/authentication/templates/migrations/create_table_migration.rb.tt +12 -0
  23. data/lib/generators/authentication/templates/models/current.rb.tt +5 -1
  24. data/lib/generators/authentication/templates/models/model.rb.tt +2 -28
  25. data/lib/generators/authentication/templates/models/session.rb.tt +7 -0
  26. data/lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt +2 -2
  27. data/lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt +4 -9
  28. data/lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt +1 -9
  29. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +4 -9
  30. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +16 -6
  31. data/lib/generators/authentication/templates/test_unit/controllers/html/cancellations_controller_test.rb.tt +1 -1
  32. data/lib/generators/authentication/templates/test_unit/controllers/html/emails_controller_test.rb.tt +3 -8
  33. data/lib/generators/authentication/templates/test_unit/controllers/html/password_resets_controller_test.rb.tt +2 -3
  34. data/lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt +3 -8
  35. data/lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt +1 -3
  36. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt +14 -7
  37. data/lib/generators/authentication/templates/test_unit/fixtures.yml.tt +0 -1
  38. data/lib/generators/authentication/templates/test_unit/sessions.yml.tt +6 -0
  39. data/lib/generators/authentication/templates/test_unit/system/cancellations_test.rb.tt +2 -2
  40. data/lib/generators/authentication/templates/test_unit/system/emails_test.rb.tt +2 -2
  41. data/lib/generators/authentication/templates/test_unit/system/password_resets_test.rb.tt +1 -1
  42. data/lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt +2 -2
  43. data/lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt +8 -1
  44. metadata +10 -7
  45. data/lib/generators/authentication/templates/erb/email_mailer/changed.html.erb.tt +0 -11
  46. data/lib/generators/authentication/templates/erb/email_mailer/changed.text.erb.tt +0 -9
  47. data/lib/generators/authentication/templates/erb/password_mailer/changed.html.erb.tt +0 -7
  48. data/lib/generators/authentication/templates/erb/password_mailer/changed.text.erb.tt +0 -5
  49. data/lib/generators/authentication/templates/mailers/email_mailer.rb.tt +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 421b9ebae03521494dfa8745a2e06f912635d3f09e34466fcdcf52040564cf7d
4
- data.tar.gz: 155653fd131eccc9aee0aeffb1b859b2b1f34507db60a17c0b337f865502322b
3
+ metadata.gz: 759478647a894dc33bcf8611a439a285cbf32d00c713ac2cc87a2cc385125a7b
4
+ data.tar.gz: eb58361a0c6d3a72e1176e041e13675bd21389ee58a32df12247bcd4bf83b9df
5
5
  SHA512:
6
- metadata.gz: 3bdd61297018da9d527e5c250c8271511bfefb375d01357d81b968eda239940191412b30ac38d89b493780eccdaddba507ebde9df908f6459f358fac10b05ee9
7
- data.tar.gz: 3d916dd8b43f4ecdc7c65660bf5c7f889324672a6d105fe258610b97b64ac1428bc0e8c74d2fa5617161d28b125f73fe156fadfd8fe6ce99136361c3f2ac41b8
6
+ metadata.gz: c56ce0caad6ea538bb4c0ba8752f35e19ad0562bbb424baa43c20fc2e38f58e008ed5832f9a7730e83df849cd55b4db5f9a61cd60da058448274712159e0257f
7
+ data.tar.gz: b33dc32e1783d49ee48e09b7ccff9959533f71d661e4aab54b50aa870fac7b674586591e4e00b1a973e846a66483619e96892fd464ed9bca1192e8cd74de4389
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (1.0.1)
4
+ authentication-zero (2.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -4,26 +4,24 @@ The purpose of authentication zero is to generate a pre-built authentication sys
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Simplest code ever**
7
8
  - Sign up
8
9
  - Email and password validations
9
10
  - Reset the user password and send reset instructions
10
11
  - Authentication by cookie (html)
11
12
  - Authentication by token (api)
12
- - Remember me (html)
13
- - Send e-mail when email is changed
14
- - Send e-mail when password is changed
13
+ - Send e-mail when sign-in to your account
14
+ - Manage multiple sessions
15
15
  - Cancel my account
16
16
  - Log out
17
17
 
18
18
  ## Security and best practices
19
19
 
20
20
  - [has_secure_password](https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password): Adds methods to set and authenticate against a BCrypt password.
21
- - [has_secure_token](https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html#method-i-has_secure_token): Adds methods to generate unique tokens.
22
21
  - [signed cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from the cookie again.
23
22
  - [httponly cookies](https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html): A cookie with the httponly attribute is inaccessible to the JavaScript, this precaution helps mitigate cross-site scripting (XSS) attacks.
24
23
  - [signed_id](https://api.rubyonrails.org/classes/ActiveRecord/SignedId.html): Returns a signed id that is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
25
24
  - [Current attributes](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html): Abstract super class that provides a thread-isolated attributes singleton, which resets automatically before and after each request.
26
- - [Callbacks](https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html): We use callbacks to send emails after changing an email or password.
27
25
  - [Action mailer](https://api.rubyonrails.org/classes/ActionMailer/Base.html): Action Mailer allows you to send email from your application using a mailer model and views.
28
26
  - [Log filtering](https://guides.rubyonrails.org/action_controller_overview.html#log-filtering): Parameters 'token' and 'password' are marked [FILTERED] in the log.
29
27
  - [Functional Tests](https://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers): In Rails, testing the various actions of a controller is a form of writing functional tests.
@@ -56,19 +54,23 @@ Add these lines to your `app/views/home/index.html.erb`:
56
54
 
57
55
  <p>Signed as <%= Current.user.email %></p>
58
56
 
57
+ <div>
58
+ <%= link_to "Change password", edit_passwords_path %>
59
+ </div>
60
+
59
61
  <div>
60
62
  <%= link_to "Change email", edit_emails_path %>
61
63
  </div>
62
64
 
63
65
  <div>
64
- <%= link_to "Change password", edit_passwords_path %>
66
+ <%= link_to "Manage Sessions", sessions_path %>
65
67
  </div>
66
68
 
67
69
  <div>
68
70
  <%= link_to "Cancel my account & delete my data", new_cancellations_path %>
69
71
  </div>
70
72
 
71
- <%= button_to "Log out", sign_out_path, method: :delete %>
73
+ <%= button_to "Log out", Current.session, method: :delete %>
72
74
  ```
73
75
 
74
76
  And you'll need to set up the default URL options for the mailer in each environment. Here is a possible configuration for `config/environments/development.rb`:
@@ -1,3 +1,3 @@
1
1
  module AuthenticationZero
2
- VERSION = "1.0.1"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require "rails/generators/active_record"
2
2
 
3
3
  class AuthenticationGenerator < Rails::Generators::NamedBase
4
+ include ActiveRecord::Generators::Migration
5
+
4
6
  class_option :api, type: :boolean, desc: "Generates API authentication"
5
7
 
6
8
  class_option :migration, type: :boolean, default: true
@@ -18,14 +20,16 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
18
20
  uncomment_lines "Gemfile", /bcrypt/
19
21
  end
20
22
 
21
- def create_migration
23
+ def create_migrations
22
24
  if options.migration
23
- invoke "migration", ["create_#{table_name}", "email:string:uniq", "password:digest", "session_token:string:uniq"]
25
+ migration_template "migrations/create_table_migration.rb", "#{db_migrate_path}/create_#{table_name}.rb"
26
+ migration_template "migrations/create_sessions_migration.rb", "#{db_migrate_path}/create_sessions.rb"
24
27
  end
25
28
  end
26
29
 
27
30
  def create_models
28
31
  template "models/model.rb", "app/models/#{file_name}.rb"
32
+ template "models/session.rb", "app/models/session.rb"
29
33
  template "models/current.rb", "app/models/current.rb"
30
34
  end
31
35
 
@@ -34,6 +38,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
34
38
  def create_fixture_file
35
39
  if options.fixture && options.fixture_replacement.nil?
36
40
  template "#{test_framework}/fixtures.yml", "test/fixtures/#{fixture_file_name}.yml"
41
+ template "#{test_framework}/sessions.yml", "test/fixtures/sessions.yml"
37
42
  end
38
43
  end
39
44
 
@@ -45,8 +50,10 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
45
50
 
46
51
  private
47
52
  def authenticate
48
- authenticate_or_request_with_http_token do |token, _options|
49
- Current.#{singular_table_name} = #{class_name}.find_signed_session_token(token)
53
+ if session = authenticate_with_http_token { |token, _| Session.find_signed(token) }
54
+ Current.session = session
55
+ else
56
+ request_http_token_authentication
50
57
  end
51
58
  end
52
59
  CODE
@@ -56,10 +63,10 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
56
63
 
57
64
  private
58
65
  def authenticate
59
- if #{singular_table_name} = #{class_name}.find_by_session_token(cookies.signed[:session_token])
60
- Current.#{singular_table_name} = #{singular_table_name}
66
+ if session = Session.find_by_id(cookies.signed[:session_token])
67
+ Current.session = session
61
68
  else
62
- redirect_to sign_in_path, alert: "You need to sign in or sign up before continuing"
69
+ redirect_to sign_in_path
63
70
  end
64
71
  end
65
72
  CODE
@@ -74,8 +81,8 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
74
81
 
75
82
  def create_views
76
83
  if options.api
77
- directory "#{template_engine}/email_mailer", "app/views/email_mailer"
78
- directory "#{template_engine}/password_mailer", "app/views/password_mailer"
84
+ directory "erb/session_mailer", "app/views/session_mailer"
85
+ directory "erb/password_mailer", "app/views/password_mailer"
79
86
  else
80
87
  directory "#{template_engine}", "app/views"
81
88
  end
@@ -91,7 +98,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
91
98
  route "resource :cancellations, only: [:new, :create]"
92
99
  route "resource :passwords, only: [:edit, :update]"
93
100
  route "resource :emails, only: [:edit, :update]"
94
- route "delete 'sign_out', to: 'sessions#destroy'"
101
+ route "resources :sessions, only: [:index, :show, :destroy]"
95
102
  route "post 'sign_up', to: 'registrations#create'"
96
103
  route "get 'sign_up', to: 'registrations#new'" unless options.api?
97
104
  route "post 'sign_in', to: 'sessions#create'"
@@ -1,17 +1,13 @@
1
1
  class PasswordResetsController < ApplicationController
2
2
  skip_before_action :authenticate
3
3
 
4
- before_action :set_<%= singular_table_name %>, only: %i[ edit update ]
5
-
6
- def edit
7
- render json: { error: "Open this link in your device" }, status: :not_found
8
- end
4
+ before_action :set_<%= singular_table_name %>, only: :update
9
5
 
10
6
  def create
11
7
  if @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
12
8
  PasswordMailer.with(<%= singular_table_name %>: @<%= singular_table_name %>).reset.deliver_later
13
9
  else
14
- render json: { error: "The email address doesn't exist in our database" }, status: :not_found
10
+ render json: { error: "Sorry, we didn't recognize that email address" }, status: :not_found
15
11
  end
16
12
  end
17
13
 
@@ -1,17 +1,39 @@
1
1
  class SessionsController < ApplicationController
2
- skip_before_action :authenticate, except: :destroy
2
+ skip_before_action :authenticate, only: :create
3
+
4
+ before_action :set_session, only: %i[ show destroy ]
5
+
6
+ def index
7
+ render json: Current.<%= singular_table_name %>.sessions.order(created_at: :desc)
8
+ end
9
+
10
+ def show
11
+ render json: @session
12
+ end
3
13
 
4
14
  def create
5
15
  @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
6
16
 
7
17
  if @<%= singular_table_name %>.try(:authenticate, params[:password])
8
- render json: { session_token: @<%= singular_table_name %>.signed_session_token }, status: :ok
18
+ session = @<%= singular_table_name %>.sessions.create!(session_params)
19
+ response.set_header("X-Session-Token", session.signed_id)
20
+
21
+ render json: session, status: :created
9
22
  else
10
- render json: { error: "Invalid email or password" }, status: :unauthorized
23
+ render json: { error: "That email or password is incorrect" }, status: :unauthorized
11
24
  end
12
25
  end
13
26
 
14
27
  def destroy
15
- Current.<%= singular_table_name %>.regenerate_session_token
28
+ @session.destroy
16
29
  end
30
+
31
+ private
32
+ def set_session
33
+ @session = Current.<%= singular_table_name %>.sessions.find(params[:id])
34
+ end
35
+
36
+ def session_params
37
+ { user_agent: request.user_agent, ip_address: request.remote_ip }
38
+ end
17
39
  end
@@ -4,6 +4,6 @@ class CancellationsController < ApplicationController
4
4
 
5
5
  def create
6
6
  Current.<%= singular_table_name %>.destroy
7
- redirect_to sign_in_path, notice: "Bye! Your account has been successfully cancelled"
7
+ redirect_to sign_in_path, notice: "Your account is closed"
8
8
  end
9
9
  end
@@ -8,7 +8,7 @@ class EmailsController < ApplicationController
8
8
  if !@<%= singular_table_name %>.authenticate(params[:current_password])
9
9
  redirect_to edit_emails_path, alert: "The current password you entered is incorrect"
10
10
  elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
11
- redirect_to root_path, notice: "Your email has been changed successfully"
11
+ redirect_to root_path, notice: "Your email has been changed"
12
12
  else
13
13
  render :edit, status: :unprocessable_entity
14
14
  end
@@ -12,9 +12,9 @@ class PasswordResetsController < ApplicationController
12
12
  def create
13
13
  if @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
14
14
  PasswordMailer.with(<%= singular_table_name %>: @<%= singular_table_name %>).reset.deliver_later
15
- redirect_to sign_in_path, notice: "You will receive an email with instructions on how to reset your password in a few minutes"
15
+ redirect_to sign_in_path, notice: "Check your email for reset instructions"
16
16
  else
17
- redirect_to new_password_resets_path(email_hint: params[:email]), alert: "The email address doesn't exist in our database"
17
+ redirect_to new_password_resets_path, alert: "Sorry, we didn't recognize that email address"
18
18
  end
19
19
  end
20
20
 
@@ -8,7 +8,7 @@ class PasswordsController < ApplicationController
8
8
  if !@<%= singular_table_name %>.authenticate(params[:current_password])
9
9
  redirect_to edit_passwords_path, alert: "The current password you entered is incorrect"
10
10
  elsif @<%= singular_table_name %>.update(<%= "#{singular_table_name}_params" %>)
11
- redirect_to root_path, notice: "Your password has been changed successfully"
11
+ redirect_to root_path, notice: "Your password has been changed"
12
12
  else
13
13
  render :edit, status: :unprocessable_entity
14
14
  end
@@ -9,8 +9,7 @@ class RegistrationsController < ApplicationController
9
9
  @<%= singular_table_name %> = <%= class_name %>.new(<%= "#{singular_table_name}_params" %>)
10
10
 
11
11
  if @<%= singular_table_name %>.save
12
- cookies.signed[:session_token] = { value: @<%= singular_table_name %>.session_token, httponly: true }
13
- redirect_to root_path, notice: "Welcome! You have signed up successfully"
12
+ redirect_to sign_in_path, notice: "Welcome! You have signed up successfully"
14
13
  else
15
14
  render :new, status: :unprocessable_entity
16
15
  end
@@ -1,5 +1,11 @@
1
1
  class SessionsController < ApplicationController
2
- skip_before_action :authenticate, except: :destroy
2
+ skip_before_action :authenticate, only: %i[ new create ]
3
+
4
+ before_action :set_session, only: :destroy
5
+
6
+ def index
7
+ @sessions = Current.<%= singular_table_name %>.sessions.order(created_at: :desc)
8
+ end
3
9
 
4
10
  def new
5
11
  @<%= singular_table_name %> = <%= class_name %>.new
@@ -9,20 +15,26 @@ class SessionsController < ApplicationController
9
15
  @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
10
16
 
11
17
  if @<%= singular_table_name %>.try(:authenticate, params[:password])
12
- if params[:remember_me] == "1"
13
- cookies.signed.permanent[:session_token] = { value: @<%= singular_table_name %>.session_token, httponly: true }
14
- else
15
- cookies.signed[:session_token] = { value: @<%= singular_table_name %>.session_token, httponly: true }
16
- end
18
+ @session = @<%= singular_table_name %>.sessions.create!(session_params)
19
+ cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
17
20
 
18
21
  redirect_to root_path, notice: "Signed in successfully"
19
22
  else
20
- redirect_to sign_in_path(email_hint: params[:email]), alert: "Invalid email or password"
23
+ redirect_to sign_in_path(email_hint: params[:email]), alert: "That email or password is incorrect"
21
24
  end
22
25
  end
23
26
 
24
27
  def destroy
25
- Current.<%= singular_table_name %>.regenerate_session_token
26
- redirect_to sign_in_path, notice: "Signed out successfully"
28
+ @session.destroy
29
+ redirect_to sessions_path, notice: "That session has been logged out"
27
30
  end
31
+
32
+ private
33
+ def set_session
34
+ @session = Current.<%= singular_table_name %>.sessions.find(params[:id])
35
+ end
36
+
37
+ def session_params
38
+ { user_agent: request.user_agent, ip_address: request.remote_ip }
39
+ end
28
40
  end
@@ -5,7 +5,7 @@
5
5
  <%%= form_with(url: password_resets_path) do |form| %>
6
6
  <div>
7
7
  <%%= form.label :email, style: "display: block" %>
8
- <%%= form.email_field :email, value: params[:email_hint], autofocus: true, required: true %>
8
+ <%%= form.email_field :email, autofocus: true, required: true %>
9
9
  </div>
10
10
 
11
11
  <div>
@@ -0,0 +1,21 @@
1
+ <p>Hey there,</p>
2
+
3
+ <p>A new device just signed in to your account (<%%= @session.<%= singular_table_name %>.email %>).</p>
4
+
5
+ <p>
6
+ <strong><%%= @session.user_agent %></strong>
7
+ <br>
8
+ <%%= @session.created_at %>
9
+ <br>
10
+ IP address: <%%= @session.ip_address %>
11
+ </p>
12
+
13
+ <p><strong>If this was you, carry on.</strong> We won't notify you about sign-ins from this device again.</p>
14
+
15
+ <p><strong>If you don't recognize this device</strong>, someone else may have accessed your account. You should immediately <%%= link_to "change your password", new_password_resets_url %>.</p>
16
+
17
+ <p><strong>Tip:</strong> It's a good idea to periodically review all of the <%%= link_to "devices and sessions", sessions_url %> in your account for suspicious activity.</p>
18
+
19
+ <hr>
20
+
21
+ <p>Have questions or need help? Just reply to this email and our support team will help you sort it out.</p>
@@ -0,0 +1,17 @@
1
+ Hey there,
2
+
3
+ A new device just signed in to your account (<%%= @session.<%= singular_table_name %>.email %>).
4
+
5
+ <%%= @session.user_agent %>
6
+
7
+ <%%= @session.created_at %>
8
+
9
+ <%%= @session.ip_address %>
10
+
11
+ If this was you, carry on. We won't notify you about sign-ins from this device again.
12
+
13
+ If you don't recognize this device, someone else may have accessed your account. You should immediately [change your password]<%%= new_password_resets_url %>.
14
+
15
+ Tip: It's a good idea to periodically review all of the [devices and sessions]<%%= sessions_url %> in your account for suspicious activity.
16
+
17
+ <p>Have questions or need help? Just reply to this email and our support team will help you sort it out.
@@ -0,0 +1,34 @@
1
+ <p style="color: green"><%%= notice %></p>
2
+
3
+ <h1>Sessions</h1>
4
+
5
+ <div id="sessions">
6
+ <%% @sessions.each do |session| %>
7
+ <div id="<%%= dom_id session %>">
8
+ <p>
9
+ <strong>User Agent:</strong>
10
+ <%%= session.user_agent %>
11
+ </p>
12
+
13
+ <p>
14
+ <strong>Ip Address:</strong>
15
+ <%%= session.ip_address %>
16
+ </p>
17
+
18
+ <p>
19
+ <strong>Created at:</strong>
20
+ <%%= session.created_at %>
21
+ </p>
22
+
23
+ </div>
24
+ <p>
25
+ <%%= button_to "Log out", session, method: :delete %>
26
+ </p>
27
+ <%% end %>
28
+ </div>
29
+
30
+ <br>
31
+
32
+ <div>
33
+ <%%= link_to "Back", root_path %>
34
+ </div>
@@ -14,11 +14,6 @@
14
14
  <%%= form.password_field :password, required: true, autocomplete: "current-password" %>
15
15
  </div>
16
16
 
17
- <div>
18
- <%%= form.check_box :remember_me %>
19
- <%%= form.label :remember_me %>
20
- </div>
21
-
22
17
  <div>
23
18
  <%%= form.submit "Sign in" %>
24
19
  </div>
@@ -1,10 +1,6 @@
1
1
  class PasswordMailer < ApplicationMailer
2
- def changed
3
- mail to: params[:<%= singular_table_name %>].email
4
- end
5
-
6
2
  def reset
7
3
  @signed_id = params[:<%= singular_table_name %>].signed_id(purpose: :password_reset, expires_in: 20.minutes)
8
- mail to: params[:<%= singular_table_name %>].email
4
+ mail to: params[:<%= singular_table_name %>].email, subject: "Reset your password"
9
5
  end
10
6
  end
@@ -0,0 +1,6 @@
1
+ class SessionMailer < ApplicationMailer
2
+ def signed_in
3
+ @session = params[:session]
4
+ mail to: @session.<%= singular_table_name %>.email, subject: "New sign-in to your account"
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :sessions do |t|
4
+ t.references :<%= singular_table_name %>, null: false, foreign_key: true
5
+ t.string :user_agent
6
+ t.string :ip_address
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ t.string :email, null: false
5
+ t.string :password_digest, null: false
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :<%= table_name %>, :email, unique: true
11
+ end
12
+ end
@@ -1,3 +1,7 @@
1
1
  class Current < ActiveSupport::CurrentAttributes
2
- attribute :<%= singular_table_name %>
2
+ attribute :session, :<%= singular_table_name %>
3
+
4
+ def session=(session)
5
+ super; Current.<%= singular_table_name %> = session.<%= singular_table_name %>
6
+ end
3
7
  end
@@ -1,7 +1,8 @@
1
1
  class <%= class_name %> < ApplicationRecord
2
- has_secure_token :session_token
3
2
  has_secure_password
4
3
 
4
+ has_many :sessions, dependent: :destroy
5
+
5
6
  validates :email, presence: true, uniqueness: true
6
7
  validates :email, format: { with: /\A[^@\s]+@[^@\s]+\z/ }
7
8
  validates_length_of :password, minimum: 8, allow_blank: true
@@ -9,31 +10,4 @@ class <%= class_name %> < ApplicationRecord
9
10
  before_validation do
10
11
  self.email = email.downcase.strip
11
12
  end
12
-
13
- after_update_commit do
14
- if self.email_previously_changed?
15
- EmailMailer.with(change: self.email_previous_change).changed.deliver_later
16
- end
17
- end
18
-
19
- after_update_commit do
20
- if self.password_digest_previously_changed?
21
- PasswordMailer.with(<%= singular_table_name %>: self).changed.deliver_later
22
- end
23
- end
24
- <% if options.api? %>
25
- def signed_session_token
26
- Rails.application.message_verifier(:session_token).generate(session_token)
27
- end
28
-
29
- def self.find_signed_session_token(signed_session_token)
30
- if session_token = Rails.application.message_verifier(:session_token).verified(signed_session_token)
31
- find_by_session_token(session_token)
32
- end
33
- end
34
-
35
- def as_json(options = {})
36
- super(options.merge(except: [:password_digest, :session_token]))
37
- end
38
- <% end -%>
39
13
  end
@@ -0,0 +1,7 @@
1
+ class Session < ApplicationRecord
2
+ belongs_to :<%= singular_table_name %>
3
+
4
+ after_create_commit do
5
+ SessionMailer.with(session: self).signed_in.deliver_later
6
+ end
7
+ end
@@ -15,6 +15,6 @@ class CancellationsControllerTest < ActionDispatch::IntegrationTest
15
15
 
16
16
  def sign_in_as(<%= singular_table_name %>)
17
17
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
18
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
19
- end
18
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
19
+ end
20
20
  end
@@ -6,17 +6,12 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest
6
6
  end
7
7
 
8
8
  test "should update email" do
9
- assert_enqueued_email_with EmailMailer, :changed, args: { change: [@<%= singular_table_name %>.email, "new_email@hey.com"] } do
10
- patch emails_url, params: { current_password: "secret123", email: "new_email@hey.com" }, headers: { "Authorization" => "Bearer #{@token}" }
11
- end
12
-
9
+ patch emails_url, params: { current_password: "secret123", email: "new_email@hey.com" }, headers: { "Authorization" => "Bearer #{@token}" }
13
10
  assert_response :success
14
11
  end
15
12
 
16
13
  test "should not update email with wrong current password" do
17
- assert_no_enqueued_emails do
18
- patch emails_url, params: { current_password: "wrong_password", email: @<%= singular_table_name %>.email }, headers: { "Authorization" => "Bearer #{@token}" }
19
- end
14
+ patch emails_url, params: { current_password: "wrong_password", email: @<%= singular_table_name %>.email }, headers: { "Authorization" => "Bearer #{@token}" }
20
15
 
21
16
  assert_response :bad_request
22
17
  assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
@@ -24,6 +19,6 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest
24
19
 
25
20
  def sign_in_as(<%= singular_table_name %>)
26
21
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
- end
22
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
23
+ end
29
24
  end
@@ -7,13 +7,6 @@ class PasswordResetsControllerTest < ActionDispatch::IntegrationTest
7
7
  @sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
8
8
  end
9
9
 
10
- test "should get edit" do
11
- get edit_password_resets_url(token: @sid)
12
-
13
- assert_response :not_found
14
- assert_equal "Open this link in your device", response.parsed_body["error"]
15
- end
16
-
17
10
  test "should send a password reset email" do
18
11
  assert_enqueued_email_with PasswordMailer, :reset, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
19
12
  post password_resets_url, params: { email: @<%= singular_table_name %>.email }
@@ -28,12 +21,11 @@ class PasswordResetsControllerTest < ActionDispatch::IntegrationTest
28
21
  end
29
22
 
30
23
  assert_response :not_found
31
- assert_equal "The email address doesn't exist in our database", response.parsed_body["error"]
24
+ assert_equal "Sorry, we didn't recognize that email address", response.parsed_body["error"]
32
25
  end
33
26
 
34
27
  test "should update password" do
35
28
  patch password_resets_url, params: { token: @sid, password: "new_password", password_confirmation: "new_password" }
36
-
37
29
  assert_response :success
38
30
  end
39
31
 
@@ -6,17 +6,12 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
6
6
  end
7
7
 
8
8
  test "should update password" do
9
- assert_enqueued_email_with PasswordMailer, :changed, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
10
- patch passwords_url, params: { current_password: "secret123", password: "new_password", password_confirmation: "new_password" }, headers: { "Authorization" => "Bearer #{@token}" }
11
- end
12
-
9
+ patch passwords_url, params: { current_password: "secret123", password: "new_password", password_confirmation: "new_password" }, headers: { "Authorization" => "Bearer #{@token}" }
13
10
  assert_response :success
14
11
  end
15
12
 
16
13
  test "should not update password with wrong current password" do
17
- assert_no_enqueued_emails do
18
- patch passwords_url, params: { current_password: "wrong_password", password: "new_password", password_confirmation: "new_password" }, headers: { "Authorization" => "Bearer #{@token}" }
19
- end
14
+ patch passwords_url, params: { current_password: "wrong_password", password: "new_password", password_confirmation: "new_password" }, headers: { "Authorization" => "Bearer #{@token}" }
20
15
 
21
16
  assert_response :bad_request
22
17
  assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
@@ -24,6 +19,6 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
24
19
 
25
20
  def sign_in_as(<%= singular_table_name %>)
26
21
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
- end
22
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
23
+ end
29
24
  end
@@ -2,12 +2,24 @@ require "test_helper"
2
2
 
3
3
  class SessionsControllerTest < ActionDispatch::IntegrationTest
4
4
  setup do
5
- @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
5
+ @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "should get index" do
9
+ get sessions_url, headers: { "Authorization" => "Bearer #{@token}" }
10
+ assert_response :success
11
+ end
12
+
13
+ test "should show session" do
14
+ get session_url(@<%= singular_table_name %>.sessions.last), headers: { "Authorization" => "Bearer #{@token}" }
15
+ assert_response :success
6
16
  end
7
17
 
8
18
  test "should sign in" do
9
19
  post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "secret123" }
10
- assert_response :success
20
+
21
+ assert_enqueued_email_with SessionMailer, :signed_in, args: { session: @<%= singular_table_name %>.sessions.last }
22
+ assert_response :created
11
23
  end
12
24
 
13
25
  test "should not sign in with wrong credentials" do
@@ -16,14 +28,12 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
16
28
  end
17
29
 
18
30
  test "should sign out" do
19
- <%= singular_table_name %>, token = sign_in_as(@<%= singular_table_name %>)
20
-
21
- delete sign_out_url, headers: { "Authorization" => "Bearer #{token}" }
31
+ delete session_url(@<%= singular_table_name %>.sessions.last), headers: { "Authorization" => "Bearer #{@token}" }
22
32
  assert_response :no_content
23
33
  end
24
34
 
25
35
  def sign_in_as(<%= singular_table_name %>)
26
36
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
37
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
28
38
  end
29
39
  end
@@ -19,6 +19,6 @@ class CancellationsControllerTest < ActionDispatch::IntegrationTest
19
19
  end
20
20
 
21
21
  def sign_in_as(<%= singular_table_name %>)
22
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
22
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); <%= singular_table_name %>
23
23
  end
24
24
  end
@@ -11,23 +11,18 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should update email" do
14
- assert_enqueued_email_with EmailMailer, :changed, args: { change: [@<%= singular_table_name %>.email, "new_email@hey.com"] } do
15
- patch emails_url, params: { current_password: "secret123", <%= singular_table_name %>: { email: "new_email@hey.com" } }
16
- end
17
-
14
+ patch emails_url, params: { current_password: "secret123", <%= singular_table_name %>: { email: "new_email@hey.com" } }
18
15
  assert_redirected_to root_path
19
16
  end
20
17
 
21
18
  test "should not update email with wrong current password" do
22
- assert_no_enqueued_emails do
23
- patch emails_url, params: { current_password: "wrong_password", <%= singular_table_name %>: { email: @<%= singular_table_name %>.email } }
24
- end
19
+ patch emails_url, params: { current_password: "wrong_password", <%= singular_table_name %>: { email: @<%= singular_table_name %>.email } }
25
20
 
26
21
  assert_redirected_to edit_emails_path
27
22
  assert_equal "The current password you entered is incorrect", flash[:alert]
28
23
  end
29
24
 
30
25
  def sign_in_as(<%= singular_table_name %>)
31
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); <%= singular_table_name %>
32
27
  end
33
28
  end
@@ -30,13 +30,12 @@ class PasswordResetsControllerTest < ActionDispatch::IntegrationTest
30
30
  post password_resets_url, params: { email: "invalid_email@hey.com" }
31
31
  end
32
32
 
33
- assert_redirected_to new_password_resets_url(email_hint: "invalid_email@hey.com")
34
- assert_equal "The email address doesn't exist in our database", flash[:alert]
33
+ assert_redirected_to new_password_resets_url
34
+ assert_equal "Sorry, we didn't recognize that email address", flash[:alert]
35
35
  end
36
36
 
37
37
  test "should update password" do
38
38
  patch password_resets_url, params: { token: @sid, <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
39
-
40
39
  assert_redirected_to sign_in_path
41
40
  end
42
41
 
@@ -11,23 +11,18 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should update password" do
14
- assert_enqueued_email_with PasswordMailer, :changed, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
15
- patch passwords_url, params: { current_password: "secret123", <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
16
- end
17
-
14
+ patch passwords_url, params: { current_password: "secret123", <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
18
15
  assert_redirected_to root_path
19
16
  end
20
17
 
21
18
  test "should not update password with wrong current password" do
22
- assert_no_enqueued_emails do
23
- patch passwords_url, params: { current_password: "wrong_password", <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
24
- end
19
+ patch passwords_url, params: { current_password: "wrong_password", <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
25
20
 
26
21
  assert_redirected_to edit_passwords_path
27
22
  assert_equal "The current password you entered is incorrect", flash[:alert]
28
23
  end
29
24
 
30
25
  def sign_in_as(<%= singular_table_name %>)
31
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); <%= singular_table_name %>
32
27
  end
33
28
  end
@@ -10,9 +10,7 @@ class RegistrationsControllerTest < ActionDispatch::IntegrationTest
10
10
  assert_difference("<%= class_name %>.count") do
11
11
  post sign_up_url, params: { <%= singular_table_name %>: { email: "lazaronixon@hey.com", password: "secret123", password_confirmation: "secret123" } }
12
12
  end
13
- assert_redirected_to root_url
14
13
 
15
- follow_redirect!
16
- assert_response :success
14
+ assert_redirected_to sign_in_url
17
15
  end
18
16
  end
@@ -5,6 +5,13 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
5
5
  @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
6
  end
7
7
 
8
+ test "should get index" do
9
+ sign_in_as @<%= singular_table_name %>
10
+
11
+ get sessions_url
12
+ assert_response :success
13
+ end
14
+
8
15
  test "should get new" do
9
16
  get sign_in_url
10
17
  assert_response :success
@@ -12,6 +19,8 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
12
19
 
13
20
  test "should sign in" do
14
21
  post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "secret123" }
22
+ assert_enqueued_email_with SessionMailer, :signed_in, args: { session: @<%= singular_table_name %>.sessions.last }
23
+
15
24
  assert_redirected_to root_url
16
25
 
17
26
  get root_url
@@ -21,25 +30,23 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
21
30
  test "should not sign in with wrong credentials" do
22
31
  post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "wrong_password" }
23
32
  assert_redirected_to sign_in_url(email_hint: @<%= singular_table_name %>.email)
24
- assert_equal "Invalid email or password", flash[:alert]
33
+ assert_equal "That email or password is incorrect", flash[:alert]
25
34
 
26
35
  get root_url
27
36
  assert_redirected_to sign_in_path
28
- assert_equal "You need to sign in or sign up before continuing", flash[:alert]
29
37
  end
30
38
 
31
39
  test "should sign out" do
32
40
  sign_in_as @<%= singular_table_name %>
33
41
 
34
- delete sign_out_url
35
- assert_redirected_to sign_in_path
42
+ delete session_url(@<%= singular_table_name %>.sessions.last)
43
+ assert_redirected_to sessions_path
36
44
 
37
- get root_path
45
+ follow_redirect!
38
46
  assert_redirected_to sign_in_path
39
- assert_equal "You need to sign in or sign up before continuing", flash[:alert]
40
47
  end
41
48
 
42
49
  def sign_in_as(<%= singular_table_name %>)
43
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
50
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); <%= singular_table_name %>
44
51
  end
45
52
  end
@@ -3,4 +3,3 @@
3
3
  lazaro_nixon:
4
4
  email: lazaronixon@hotmail.com
5
5
  password_digest: <%%= BCrypt::Password.create("secret123") %>
6
- session_token: <%%= SecureRandom.base58(24) %>
@@ -0,0 +1,6 @@
1
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
+
3
+ lazaro_nixon_ios:
4
+ <%= singular_table_name %>: lazaro_nixon
5
+ user_agent: Device iOS
6
+ ip_address: 127.0.0.1
@@ -9,7 +9,7 @@ class CancellationsTest < ApplicationSystemTestCase
9
9
  click_on "Cancel my account & delete my data"
10
10
  click_on "OK, close my account"
11
11
 
12
- assert_text "Bye! Your account has been successfully cancelled"
12
+ assert_text "Your account is closed"
13
13
  end
14
14
 
15
15
  def sign_in_as(<%= singular_table_name %>)
@@ -19,5 +19,5 @@ class CancellationsTest < ApplicationSystemTestCase
19
19
  click_on "Sign in"
20
20
 
21
21
  return <%= singular_table_name %>
22
- end
22
+ end
23
23
  end
@@ -12,7 +12,7 @@ class EmailsTest < ApplicationSystemTestCase
12
12
  fill_in "New email", with: "new_email@hey.com"
13
13
  click_on "Save changes"
14
14
 
15
- assert_text "Your email has been changed successfully"
15
+ assert_text "Your email has been changed"
16
16
  end
17
17
 
18
18
  def sign_in_as(<%= singular_table_name %>)
@@ -22,5 +22,5 @@ class EmailsTest < ApplicationSystemTestCase
22
22
  click_on "Sign in"
23
23
 
24
24
  return <%= singular_table_name %>
25
- end
25
+ end
26
26
  end
@@ -13,7 +13,7 @@ class PasswordResetsTest < ApplicationSystemTestCase
13
13
  fill_in "Email", with: @<%= singular_table_name %>.email
14
14
  click_on "Send password reset email"
15
15
 
16
- assert_text "You will receive an email with instructions on how to reset your password in a few minutes"
16
+ assert_text "Check your email for reset instructions"
17
17
  end
18
18
 
19
19
  test "updating password" do
@@ -13,7 +13,7 @@ class PasswordsTest < ApplicationSystemTestCase
13
13
  fill_in "Confirm new password", with: "new_password"
14
14
  click_on "Save changes"
15
15
 
16
- assert_text "Your password has been changed successfully"
16
+ assert_text "Your password has been changed"
17
17
  end
18
18
 
19
19
  def sign_in_as(<%= singular_table_name %>)
@@ -23,5 +23,5 @@ class PasswordsTest < ApplicationSystemTestCase
23
23
  click_on "Sign in"
24
24
 
25
25
  return <%= singular_table_name %>
26
- end
26
+ end
27
27
  end
@@ -5,6 +5,13 @@ class SessionsTest < ApplicationSystemTestCase
5
5
  @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
6
  end
7
7
 
8
+ test "visiting the index" do
9
+ sign_in_as @<%= singular_table_name %>
10
+
11
+ click_on "Manage Sessions"
12
+ assert_selector "h1", text: "Sessions"
13
+ end
14
+
8
15
  test "signing in" do
9
16
  visit sign_in_url
10
17
  fill_in "Email", with: @<%= singular_table_name %>.email
@@ -18,7 +25,7 @@ class SessionsTest < ApplicationSystemTestCase
18
25
  sign_in_as @<%= singular_table_name %>
19
26
 
20
27
  click_on "Log out"
21
- assert_text "Signed out successfully"
28
+ assert_selector "h1", text: "Sign in"
22
29
  end
23
30
 
24
31
  def sign_in_as(<%= singular_table_name %>)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authentication-zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nixon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-21 00:00:00.000000000 Z
11
+ date: 2022-02-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -44,22 +44,24 @@ files:
44
44
  - lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt
45
45
  - lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt
46
46
  - lib/generators/authentication/templates/erb/cancellations/new.html.erb.tt
47
- - lib/generators/authentication/templates/erb/email_mailer/changed.html.erb.tt
48
- - lib/generators/authentication/templates/erb/email_mailer/changed.text.erb.tt
49
47
  - lib/generators/authentication/templates/erb/emails/edit.html.erb.tt
50
- - lib/generators/authentication/templates/erb/password_mailer/changed.html.erb.tt
51
- - lib/generators/authentication/templates/erb/password_mailer/changed.text.erb.tt
52
48
  - lib/generators/authentication/templates/erb/password_mailer/reset.html.erb.tt
53
49
  - lib/generators/authentication/templates/erb/password_mailer/reset.text.erb.tt
54
50
  - lib/generators/authentication/templates/erb/password_resets/edit.html.erb.tt
55
51
  - lib/generators/authentication/templates/erb/password_resets/new.html.erb.tt
56
52
  - lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt
57
53
  - lib/generators/authentication/templates/erb/registrations/new.html.erb.tt
54
+ - lib/generators/authentication/templates/erb/session_mailer/signed_in.html.erb.tt
55
+ - lib/generators/authentication/templates/erb/session_mailer/signed_in.text.erb.tt
56
+ - lib/generators/authentication/templates/erb/sessions/index.html.erb.tt
58
57
  - lib/generators/authentication/templates/erb/sessions/new.html.erb.tt
59
- - lib/generators/authentication/templates/mailers/email_mailer.rb.tt
60
58
  - lib/generators/authentication/templates/mailers/password_mailer.rb.tt
59
+ - lib/generators/authentication/templates/mailers/session_mailer.rb.tt
60
+ - lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt
61
+ - lib/generators/authentication/templates/migrations/create_table_migration.rb.tt
61
62
  - lib/generators/authentication/templates/models/current.rb.tt
62
63
  - lib/generators/authentication/templates/models/model.rb.tt
64
+ - lib/generators/authentication/templates/models/session.rb.tt
63
65
  - lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt
64
66
  - lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt
65
67
  - lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt
@@ -73,6 +75,7 @@ files:
73
75
  - lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt
74
76
  - lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt
75
77
  - lib/generators/authentication/templates/test_unit/fixtures.yml.tt
78
+ - lib/generators/authentication/templates/test_unit/sessions.yml.tt
76
79
  - lib/generators/authentication/templates/test_unit/system/cancellations_test.rb.tt
77
80
  - lib/generators/authentication/templates/test_unit/system/emails_test.rb.tt
78
81
  - lib/generators/authentication/templates/test_unit/system/password_resets_test.rb.tt
@@ -1,11 +0,0 @@
1
- <p>Hey there,</p>
2
-
3
- <p>We just wanted to confirm that your email address has been updated.</p>
4
-
5
- <p><strong>Before, it was: <%%= @previous_email %></strong></p>
6
-
7
- <p><strong>Now it is set to: <%%= @current_email %></strong></p>
8
-
9
- <hr>
10
-
11
- <p>If you didn't make this change, someone else may have access to your account. If you think that may be the case, please reply to this email and our support team will help you out.</p>
@@ -1,9 +0,0 @@
1
- Hey there,
2
-
3
- We just wanted to confirm that your email address has been updated.
4
-
5
- Before, it was: <%%= @previous_email %>
6
-
7
- Now it is set to: <%%= @current_email %>
8
-
9
- If you didn't make this change, someone else may have access to your account. If you think that may be the case, please reply to this email and our support team will help you out.
@@ -1,7 +0,0 @@
1
- <p>Hey there,</p>
2
-
3
- <p>We just wanted to confirm that your password has been updated.</p>
4
-
5
- <hr>
6
-
7
- <p>If you didn't make this change, someone else may have access to your account. If you think that may be the case, please reply to this email and our support team will help you out.</p>
@@ -1,5 +0,0 @@
1
- Hey there,
2
-
3
- We just wanted to confirm that your password has been updated.
4
-
5
- If you didn't make this change, someone else may have access to your account. If you think that may be the case, please reply to this email and our support team will help you out.
@@ -1,6 +0,0 @@
1
- class EmailMailer < ApplicationMailer
2
- def changed
3
- @previous_email, @current_email = params[:change]
4
- mail to: @previous_email
5
- end
6
- end