authentication-zero 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +7 -4
  4. data/lib/authentication_zero/version.rb +1 -1
  5. data/lib/generators/authentication/authentication_generator.rb +20 -13
  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 +25 -3
  8. data/lib/generators/authentication/templates/controllers/html/password_resets_controller.rb.tt +1 -1
  9. data/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt +7 -1
  10. data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +20 -8
  11. data/lib/generators/authentication/templates/erb/password_resets/new.html.erb.tt +1 -1
  12. data/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt +34 -0
  13. data/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +0 -5
  14. data/lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt +11 -0
  15. data/lib/generators/authentication/templates/migrations/create_table_migration.rb.tt +12 -0
  16. data/lib/generators/authentication/templates/models/current.rb.tt +5 -1
  17. data/lib/generators/authentication/templates/models/model.rb.tt +2 -16
  18. data/lib/generators/authentication/templates/models/session.rb.tt +3 -0
  19. data/lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt +2 -2
  20. data/lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt +2 -2
  21. data/lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt +1 -9
  22. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +2 -2
  23. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +14 -6
  24. data/lib/generators/authentication/templates/test_unit/controllers/html/password_resets_controller_test.rb.tt +2 -3
  25. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt +10 -5
  26. data/lib/generators/authentication/templates/test_unit/fixtures.yml.tt +0 -1
  27. data/lib/generators/authentication/templates/test_unit/sessions.yml.tt +6 -0
  28. data/lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt +8 -1
  29. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30572c49dd754b2b621acf5adad550f2ad179f3bb3af559748e296b16b04c529
4
- data.tar.gz: 569ac3a9411562d1a2bf5ee049b3cbf1350fc43cc1a2a5e837ca421f7994ae63
3
+ metadata.gz: c0359a2a997ced43e3eb97612156d7ffe3206aa8a75ede90ad37dbdf0d0a9269
4
+ data.tar.gz: 9a50df4bf9804a3da3bb1ee753b7ecd027a336f0624de5a9c5d1cfec1b5354b1
5
5
  SHA512:
6
- metadata.gz: a78c56a451d289464bb25e4d86f1765a5c74c032f2c19aaa7268cb3653680fdb7bae3242c911f3d7d6402d3cd22d771ab9cef1316866b8fd6d89ecf6991d2772
7
- data.tar.gz: 7e245a32b1150f57ceb6941cdffce360cf9ac67d49ef583b4e5e1d6ee0afcb0d593b7c2afb67e66369f77ede9f8c347203d109537e26c184fd25ce1c8ddb0765
6
+ metadata.gz: 45b51a6f24b135e1273d076683c1d406755e30ec012c4e5ec632a158ef0bb8432cb9c461254b044ba7c491717eaa95571e1cce85bb6560b19f35cf1ac03a7000
7
+ data.tar.gz: 2dd271538d229d7a88df027a44f06e59a4f0092cdc6bb8de214596dfde3cb52c2339e5659c6a8331ba69440a25030ec6c2620255f5d483e0f980a042277a28ae
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (1.0.0)
4
+ authentication-zero (2.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -9,7 +9,7 @@ The purpose of authentication zero is to generate a pre-built authentication sys
9
9
  - Reset the user password and send reset instructions
10
10
  - Authentication by cookie (html)
11
11
  - Authentication by token (api)
12
- - Remember me (html)
12
+ - Manage sessions
13
13
  - Send e-mail when email is changed
14
14
  - Send e-mail when password is changed
15
15
  - Cancel my account
@@ -18,7 +18,6 @@ The purpose of authentication zero is to generate a pre-built authentication sys
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.
@@ -56,19 +55,23 @@ Add these lines to your `app/views/home/index.html.erb`:
56
55
 
57
56
  <p>Signed as <%= Current.user.email %></p>
58
57
 
58
+ <div>
59
+ <%= link_to "Change password", edit_passwords_path %>
60
+ </div>
61
+
59
62
  <div>
60
63
  <%= link_to "Change email", edit_emails_path %>
61
64
  </div>
62
65
 
63
66
  <div>
64
- <%= link_to "Change password", edit_passwords_path %>
67
+ <%= link_to "Manage Sessions", sessions_path %>
65
68
  </div>
66
69
 
67
70
  <div>
68
71
  <%= link_to "Cancel my account & delete my data", new_cancellations_path %>
69
72
  </div>
70
73
 
71
- <%= button_to "Log out", sign_out_path, method: :delete %>
74
+ <%= button_to "Log out", Current.session, method: :delete %>
72
75
  ```
73
76
 
74
77
  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.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,12 +1,14 @@
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
- class_option :migration, type: :boolean
8
+ class_option :migration, type: :boolean, default: true
7
9
  class_option :test_framework, type: :string, desc: "Test framework to be invoked"
8
10
 
9
- class_option :fixture, type: :boolean
11
+ class_option :fixture, type: :boolean, default: true
10
12
  class_option :system_tests, type: :string, desc: "Skip system test files"
11
13
 
12
14
  class_option :skip_routes, type: :boolean
@@ -18,22 +20,25 @@ 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
 
32
36
  hook_for :fixture_replacement
33
37
 
34
38
  def create_fixture_file
35
- if options.fixture
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/email_mailer", "app/views/email_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
23
  render json: { error: "Invalid email or password" }, 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.user.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
@@ -14,7 +14,7 @@ class PasswordResetsController < ApplicationController
14
14
  PasswordMailer.with(<%= singular_table_name %>: @<%= singular_table_name %>).reset.deliver_later
15
15
  redirect_to sign_in_path, notice: "You will receive an email with instructions on how to reset your password in a few minutes"
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
 
@@ -9,7 +9,9 @@ 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 }
12
+ @session = @user.sessions.create!(session_params)
13
+ cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
14
+
13
15
  redirect_to root_path, notice: "Welcome! You have signed up successfully"
14
16
  else
15
17
  render :new, status: :unprocessable_entity
@@ -20,4 +22,8 @@ class RegistrationsController < ApplicationController
20
22
  def <%= "#{singular_table_name}_params" %>
21
23
  params.require(:<%= singular_table_name %>).permit(:email, :password, :password_confirmation)
22
24
  end
25
+
26
+ def session_params
27
+ { user_agent: request.user_agent, ip_address: request.remote_ip }
28
+ end
23
29
  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,11 +15,8 @@ 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
@@ -22,7 +25,16 @@ class SessionsController < ApplicationController
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.user.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,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>
@@ -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
@@ -21,19 +22,4 @@ class <%= class_name %> < ApplicationRecord
21
22
  PasswordMailer.with(<%= singular_table_name %>: self).changed.deliver_later
22
23
  end
23
24
  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
25
  end
@@ -0,0 +1,3 @@
1
+ class Session < ApplicationRecord
2
+ belongs_to :<%= singular_table_name %>
3
+ 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
@@ -24,6 +24,6 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest
24
24
 
25
25
  def sign_in_as(<%= singular_table_name %>)
26
26
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
- end
27
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
28
+ end
29
29
  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
 
@@ -24,6 +24,6 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
24
24
 
25
25
  def sign_in_as(<%= singular_table_name %>)
26
26
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
- end
27
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
28
+ end
29
29
  end
@@ -2,12 +2,22 @@ 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
+ assert_response :created
11
21
  end
12
22
 
13
23
  test "should not sign in with wrong credentials" do
@@ -16,14 +26,12 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
16
26
  end
17
27
 
18
28
  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}" }
29
+ delete session_url(@<%= singular_table_name %>.sessions.last), headers: { "Authorization" => "Bearer #{@token}" }
22
30
  assert_response :no_content
23
31
  end
24
32
 
25
33
  def sign_in_as(<%= singular_table_name %>)
26
34
  post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
- [<%= singular_table_name %>, response.parsed_body["session_token"]]
35
+ [<%= singular_table_name %>, response.headers["X-Session-Token"]]
28
36
  end
29
37
  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
 
@@ -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
@@ -25,18 +32,16 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
25
32
 
26
33
  get root_url
27
34
  assert_redirected_to sign_in_path
28
- assert_equal "You need to sign in or sign up before continuing", flash[:alert]
29
35
  end
30
36
 
31
37
  test "should sign out" do
32
38
  sign_in_as @<%= singular_table_name %>
33
39
 
34
- delete sign_out_url
35
- assert_redirected_to sign_in_path
40
+ delete session_url(@<%= singular_table_name %>.sessions.last)
41
+ assert_redirected_to sessions_path
36
42
 
37
- get root_path
43
+ follow_redirect!
38
44
  assert_redirected_to sign_in_path
39
- assert_equal "You need to sign in or sign up before continuing", flash[:alert]
40
45
  end
41
46
 
42
47
  def sign_in_as(<%= singular_table_name %>)
@@ -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
+ user: lazaro_nixon
5
+ user_agent: Device iOS
6
+ ip_address: 127.0.0.1
@@ -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.0
4
+ version: 2.0.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:
@@ -55,11 +55,15 @@ files:
55
55
  - lib/generators/authentication/templates/erb/password_resets/new.html.erb.tt
56
56
  - lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt
57
57
  - lib/generators/authentication/templates/erb/registrations/new.html.erb.tt
58
+ - lib/generators/authentication/templates/erb/sessions/index.html.erb.tt
58
59
  - lib/generators/authentication/templates/erb/sessions/new.html.erb.tt
59
60
  - lib/generators/authentication/templates/mailers/email_mailer.rb.tt
60
61
  - lib/generators/authentication/templates/mailers/password_mailer.rb.tt
62
+ - lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt
63
+ - lib/generators/authentication/templates/migrations/create_table_migration.rb.tt
61
64
  - lib/generators/authentication/templates/models/current.rb.tt
62
65
  - lib/generators/authentication/templates/models/model.rb.tt
66
+ - lib/generators/authentication/templates/models/session.rb.tt
63
67
  - lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt
64
68
  - lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt
65
69
  - lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt
@@ -73,6 +77,7 @@ files:
73
77
  - lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt
74
78
  - lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt
75
79
  - lib/generators/authentication/templates/test_unit/fixtures.yml.tt
80
+ - lib/generators/authentication/templates/test_unit/sessions.yml.tt
76
81
  - lib/generators/authentication/templates/test_unit/system/cancellations_test.rb.tt
77
82
  - lib/generators/authentication/templates/test_unit/system/emails_test.rb.tt
78
83
  - lib/generators/authentication/templates/test_unit/system/password_resets_test.rb.tt