authentication-zero 0.0.22 → 1.0.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +4 -1
  4. data/lib/authentication_zero/version.rb +1 -1
  5. data/lib/generators/authentication/USAGE +7 -2
  6. data/lib/generators/authentication/authentication_generator.rb +99 -56
  7. data/lib/generators/authentication/templates/controllers/api/password_resets_controller.rb.tt +3 -2
  8. data/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt +1 -1
  9. data/lib/generators/authentication/templates/controllers/html/password_resets_controller.rb.tt +2 -1
  10. data/lib/generators/authentication/templates/{views → erb}/cancellations/new.html.erb.tt +0 -0
  11. data/lib/generators/authentication/templates/{views → erb}/email_mailer/changed.html.erb.tt +0 -0
  12. data/lib/generators/authentication/templates/{views → erb}/email_mailer/changed.text.erb.tt +0 -0
  13. data/lib/generators/authentication/templates/{views → erb}/emails/edit.html.erb.tt +0 -0
  14. data/lib/generators/authentication/templates/{views → erb}/password_mailer/changed.html.erb.tt +0 -0
  15. data/lib/generators/authentication/templates/{views → erb}/password_mailer/changed.text.erb.tt +0 -0
  16. data/lib/generators/authentication/templates/{views → erb}/password_mailer/reset.html.erb.tt +0 -0
  17. data/lib/generators/authentication/templates/{views → erb}/password_mailer/reset.text.erb.tt +0 -0
  18. data/lib/generators/authentication/templates/{views → erb}/password_resets/edit.html.erb.tt +0 -0
  19. data/lib/generators/authentication/templates/{views → erb}/password_resets/new.html.erb.tt +0 -0
  20. data/lib/generators/authentication/templates/{views → erb}/passwords/edit.html.erb.tt +0 -0
  21. data/lib/generators/authentication/templates/{views → erb}/registrations/new.html.erb.tt +0 -0
  22. data/lib/generators/authentication/templates/{views → erb}/sessions/new.html.erb.tt +0 -0
  23. data/lib/generators/authentication/templates/mailers/password_mailer.rb.tt +1 -1
  24. data/lib/generators/authentication/templates/models/{resource.rb.tt → model.rb.tt} +8 -5
  25. data/lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt +20 -0
  26. data/lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt +29 -0
  27. data/lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt +46 -0
  28. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +29 -0
  29. data/lib/generators/authentication/templates/test_unit/controllers/api/registrations_controller_test.rb.tt +11 -0
  30. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +29 -0
  31. data/lib/generators/authentication/templates/test_unit/controllers/html/cancellations_controller_test.rb.tt +24 -0
  32. data/lib/generators/authentication/templates/test_unit/controllers/html/emails_controller_test.rb.tt +33 -0
  33. data/lib/generators/authentication/templates/test_unit/controllers/html/password_resets_controller_test.rb.tt +49 -0
  34. data/lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt +33 -0
  35. data/lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt +18 -0
  36. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt +45 -0
  37. data/lib/generators/authentication/templates/test_unit/fixtures.yml.tt +6 -0
  38. data/lib/generators/authentication/templates/test_unit/system/cancellations_test.rb.tt +23 -0
  39. data/lib/generators/authentication/templates/test_unit/system/emails_test.rb.tt +26 -0
  40. data/lib/generators/authentication/templates/test_unit/system/password_resets_test.rb.tt +28 -0
  41. data/lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt +27 -0
  42. data/lib/generators/authentication/templates/test_unit/system/registrations_test.rb.tt +15 -0
  43. data/lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt +32 -0
  44. metadata +35 -17
  45. data/lib/generators/authentication/templates/migration.rb.tt +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f745db607e21f39bb22fec9452b30147cebbf4a41d49150450c14035b00b1d0e
4
- data.tar.gz: f412264a06233f8571dad3640bf9b2ee853e289ad168ad5e12f5fa8d3a6bfb04
3
+ metadata.gz: 421b9ebae03521494dfa8745a2e06f912635d3f09e34466fcdcf52040564cf7d
4
+ data.tar.gz: 155653fd131eccc9aee0aeffb1b859b2b1f34507db60a17c0b337f865502322b
5
5
  SHA512:
6
- metadata.gz: d28443fe294ac245251268f5130dc7c4776a793fcff46e89e37fbb34c419455735be7d63ac7a3fa4fbaaac976806e37f8770be6c32a44663cdee4374b2b2ffb3
7
- data.tar.gz: 902d2c094e0d7fb1cd5c10a8b81d733fda6cb9580baf2312591cce588fe82b9b4302f80a41c6e75bd8dae037411028968cc82ff2159fb4155891f7ebd66587c1
6
+ metadata.gz: 3bdd61297018da9d527e5c250c8271511bfefb375d01357d81b968eda239940191412b30ac38d89b493780eccdaddba507ebde9df908f6459f358fac10b05ee9
7
+ data.tar.gz: 3d916dd8b43f4ecdc7c65660bf5c7f889324672a6d105fe258610b97b64ac1428bc0e8c74d2fa5617161d28b125f73fe156fadfd8fe6ce99136361c3f2ac41b8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (0.0.22)
4
+ authentication-zero (1.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -26,13 +26,14 @@ The purpose of authentication zero is to generate a pre-built authentication sys
26
26
  - [Callbacks](https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html): We use callbacks to send emails after changing an email or password.
27
27
  - [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
28
  - [Log filtering](https://guides.rubyonrails.org/action_controller_overview.html#log-filtering): Parameters 'token' and 'password' are marked [FILTERED] in the log.
29
+ - [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.
30
+ - [System Testing](https://guides.rubyonrails.org/testing.html#system-testing): System tests allow you to test user interactions with your application, running tests in either a real or a headless browser.
29
31
 
30
32
  ## Installation
31
33
 
32
34
  Add this lines to your application's Gemfile:
33
35
 
34
36
  ```ruby
35
- gem "bcrypt"
36
37
  gem "authentication-zero"
37
38
  ```
38
39
 
@@ -82,6 +83,8 @@ config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
82
83
  $ rails generate authentication user
83
84
  ```
84
85
 
86
+ Then run `bundle install` again!
87
+
85
88
  ## Development
86
89
 
87
90
  To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
@@ -1,3 +1,3 @@
1
1
  module AuthenticationZero
2
- VERSION = "0.0.22"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -1,6 +1,11 @@
1
1
  Description:
2
- The purpose of authentication zero is to generate a pre-built authentication system into a rails application that follows both security and rails best practices.
3
- By generating code into the user's application instead of using a library, the user has complete freedom to modify the authentication system so it works best with their app.
2
+ The purpose of authentication zero is to generate a pre-built
3
+ authentication system into a rails application that
4
+ follows both security and rails best practices.
5
+
6
+ By generating code into the user's application
7
+ instead of using a library, the user has complete freedom
8
+ to modify the authentication system so it works best with their app.
4
9
 
5
10
  Example:
6
11
  bin/rails generate authentication user
@@ -1,84 +1,127 @@
1
1
  require "rails/generators/active_record"
2
2
 
3
3
  class AuthenticationGenerator < Rails::Generators::NamedBase
4
- include ActiveRecord::Generators::Migration
5
-
6
4
  class_option :api, type: :boolean, desc: "Generates API authentication"
7
5
 
6
+ class_option :migration, type: :boolean, default: true
7
+ class_option :test_framework, type: :string, desc: "Test framework to be invoked"
8
+
9
+ class_option :fixture, type: :boolean, default: true
10
+ class_option :system_tests, type: :string, desc: "Skip system test files"
11
+
12
+ class_option :skip_routes, type: :boolean
13
+ class_option :template_engine, type: :string, desc: "Template engine to be invoked"
14
+
8
15
  source_root File.expand_path("templates", __dir__)
9
16
 
10
- def create_controllers
11
- if options.api
12
- directory "controllers/api", "app/controllers"
13
- else
14
- directory "controllers/html", "app/controllers"
17
+ def add_bcrypt
18
+ uncomment_lines "Gemfile", /bcrypt/
19
+ end
20
+
21
+ def create_migration
22
+ if options.migration
23
+ invoke "migration", ["create_#{table_name}", "email:string:uniq", "password:digest", "session_token:string:uniq"]
15
24
  end
16
25
  end
17
26
 
18
- def create_mailers
19
- template "mailers/email_mailer.rb", "app/mailers/email_mailer.rb"
20
- template "mailers/password_mailer.rb", "app/mailers/password_mailer.rb"
27
+ def create_models
28
+ template "models/model.rb", "app/models/#{file_name}.rb"
29
+ template "models/current.rb", "app/models/current.rb"
30
+ end
31
+
32
+ hook_for :fixture_replacement
33
+
34
+ def create_fixture_file
35
+ if options.fixture && options.fixture_replacement.nil?
36
+ template "#{test_framework}/fixtures.yml", "test/fixtures/#{fixture_file_name}.yml"
37
+ end
38
+ end
39
+
40
+ def add_application_controller_methods
41
+ api_code = <<~CODE
42
+ include ActionController::HttpAuthentication::Token::ControllerMethods
43
+
44
+ before_action :authenticate
45
+
46
+ private
47
+ def authenticate
48
+ authenticate_or_request_with_http_token do |token, _options|
49
+ Current.#{singular_table_name} = #{class_name}.find_signed_session_token(token)
50
+ end
51
+ end
52
+ CODE
53
+
54
+ html_code = <<~CODE
55
+ before_action :authenticate
56
+
57
+ private
58
+ 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}
61
+ else
62
+ redirect_to sign_in_path, alert: "You need to sign in or sign up before continuing"
63
+ end
64
+ end
65
+ CODE
66
+
67
+ inject_code = options.api? ? api_code : html_code
68
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController", optimize_indentation(inject_code, 2), verbose: false
69
+ end
70
+
71
+ def create_controllers
72
+ directory "controllers/#{format_folder}", "app/controllers"
21
73
  end
22
74
 
23
75
  def create_views
24
76
  if options.api
25
- directory "views/email_mailer", "app/views/email_mailer"
26
- directory "views/password_mailer", "app/views/password_mailer"
77
+ directory "#{template_engine}/email_mailer", "app/views/email_mailer"
78
+ directory "#{template_engine}/password_mailer", "app/views/password_mailer"
27
79
  else
28
- directory "views", "app/views"
80
+ directory "#{template_engine}", "app/views"
29
81
  end
30
82
  end
31
83
 
32
- def create_models
33
- template "models/current.rb", "app/models/current.rb"
34
- template "models/resource.rb", "app/models/#{singular_table_name}.rb"
84
+ def create_mailers
85
+ directory "mailers", "app/mailers"
35
86
  end
36
87
 
37
- def create_migrations
38
- migration_template "migration.rb", "#{db_migrate_path}/create_#{file_name}.rb"
88
+ def add_routes
89
+ unless options.skip_routes
90
+ route "resource :password_resets, only: [:new, :edit, :create, :update]"
91
+ route "resource :cancellations, only: [:new, :create]"
92
+ route "resource :passwords, only: [:edit, :update]"
93
+ route "resource :emails, only: [:edit, :update]"
94
+ route "delete 'sign_out', to: 'sessions#destroy'"
95
+ route "post 'sign_up', to: 'registrations#create'"
96
+ route "get 'sign_up', to: 'registrations#new'" unless options.api?
97
+ route "post 'sign_in', to: 'sessions#create'"
98
+ route "get 'sign_in', to: 'sessions#new'" unless options.api?
99
+ end
39
100
  end
40
101
 
41
- def add_routes
42
- route "resource :password_resets, only: [:new, :edit, :create, :update]"
43
- route "resource :cancellations, only: [:new, :create]"
44
- route "resource :passwords, only: [:edit, :update]"
45
- route "resource :emails, only: [:edit, :update]"
46
- route "delete 'sign_out', to: 'sessions#destroy'"
47
- route "post 'sign_up', to: 'registrations#create'"
48
- route "get 'sign_up', to: 'registrations#new'" unless options.api?
49
- route "post 'sign_in', to: 'sessions#create'"
50
- route "get 'sign_in', to: 'sessions#new'" unless options.api?
102
+ def create_test_files
103
+ directory "#{test_framework}/controllers/#{format_folder}", "test/controllers"
104
+ directory "#{system_tests}/system", "test/system" if system_tests?
51
105
  end
52
106
 
53
- def add_application_controller_methods
54
- if options.api?
55
- inject_into_class "app/controllers/application_controller.rb", "ApplicationController", verbose: false do <<~CODE
56
- include ActionController::HttpAuthentication::Token::ControllerMethods
107
+ private
108
+ def format_folder
109
+ options.api ? "api" : "html"
110
+ end
57
111
 
58
- before_action :authenticate
112
+ def template_engine
113
+ options.template_engine
114
+ end
59
115
 
60
- private
61
- def authenticate
62
- authenticate_or_request_with_http_token do |token, _options|
63
- Current.#{singular_table_name} = #{class_name}.find_signed_session_token(token)
64
- end
65
- end
66
- CODE
67
- end
68
- else
69
- inject_into_class "app/controllers/application_controller.rb", "ApplicationController", verbose: false do <<~CODE
70
- before_action :authenticate
71
-
72
- private
73
- def authenticate
74
- if #{singular_table_name} = #{class_name}.find_by_session_token(cookies.signed[:session_token])
75
- Current.#{singular_table_name} = #{singular_table_name}
76
- else
77
- redirect_to sign_in_path, alert: "You need to sign in or sign up before continuing"
78
- end
79
- end
80
- CODE
81
- end
116
+ def test_framework
117
+ options.test_framework
118
+ end
119
+
120
+ def system_tests
121
+ options.system_tests
122
+ end
123
+
124
+ def system_tests?
125
+ !options.api? && options.system_tests
82
126
  end
83
- end
84
127
  end
@@ -1,5 +1,6 @@
1
1
  class PasswordResetsController < ApplicationController
2
2
  skip_before_action :authenticate
3
+
3
4
  before_action :set_<%= singular_table_name %>, only: %i[ edit update ]
4
5
 
5
6
  def edit
@@ -10,7 +11,7 @@ class PasswordResetsController < ApplicationController
10
11
  if @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
11
12
  PasswordMailer.with(<%= singular_table_name %>: @<%= singular_table_name %>).reset.deliver_later
12
13
  else
13
- render json: { error: "The email address doesn't exist in our database" }, status: :bad_request
14
+ render json: { error: "The email address doesn't exist in our database" }, status: :not_found
14
15
  end
15
16
  end
16
17
 
@@ -24,7 +25,7 @@ class PasswordResetsController < ApplicationController
24
25
 
25
26
  private
26
27
  def set_<%= singular_table_name %>
27
- @<%= singular_table_name %> = <%= class_name %>.find_signed!(params[:token], purpose: "password_reset")
28
+ @<%= singular_table_name %> = <%= class_name %>.find_signed!(params[:token], purpose: :password_reset)
28
29
  rescue ActiveSupport::MessageVerifier::InvalidSignature
29
30
  render json: { error: "Your token has expired, please request a new one" }, status: :bad_request
30
31
  end
@@ -5,7 +5,7 @@ class SessionsController < ApplicationController
5
5
  @<%= singular_table_name %> = <%= class_name %>.find_by_email(params[:email])
6
6
 
7
7
  if @<%= singular_table_name %>.try(:authenticate, params[:password])
8
- render json: { session_token: @<%= singular_table_name %>.signed_session_token }
8
+ render json: { session_token: @<%= singular_table_name %>.signed_session_token }, status: :ok
9
9
  else
10
10
  render json: { error: "Invalid email or password" }, status: :unauthorized
11
11
  end
@@ -1,5 +1,6 @@
1
1
  class PasswordResetsController < ApplicationController
2
2
  skip_before_action :authenticate
3
+
3
4
  before_action :set_<%= singular_table_name %>, only: %i[ edit update ]
4
5
 
5
6
  def new
@@ -27,7 +28,7 @@ class PasswordResetsController < ApplicationController
27
28
 
28
29
  private
29
30
  def set_<%= singular_table_name %>
30
- @<%= singular_table_name %> = <%= class_name %>.find_signed!(params[:token], purpose: "password_reset")
31
+ @<%= singular_table_name %> = <%= class_name %>.find_signed!(params[:token], purpose: :password_reset)
31
32
  rescue ActiveSupport::MessageVerifier::InvalidSignature
32
33
  redirect_to new_password_resets_path, alert: "Your token has expired, please request a new one"
33
34
  end
@@ -4,7 +4,7 @@ class PasswordMailer < ApplicationMailer
4
4
  end
5
5
 
6
6
  def reset
7
- @signed_id = params[:<%= singular_table_name %>].signed_id(purpose: "password_reset", expires_in: 20.minutes)
7
+ @signed_id = params[:<%= singular_table_name %>].signed_id(purpose: :password_reset, expires_in: 20.minutes)
8
8
  mail to: params[:<%= singular_table_name %>].email
9
9
  end
10
10
  end
@@ -1,6 +1,6 @@
1
1
  class <%= class_name %> < ApplicationRecord
2
- has_secure_password :password
3
2
  has_secure_token :session_token
3
+ has_secure_password
4
4
 
5
5
  validates :email, presence: true, uniqueness: true
6
6
  validates :email, format: { with: /\A[^@\s]+@[^@\s]+\z/ }
@@ -21,16 +21,19 @@ class <%= class_name %> < ApplicationRecord
21
21
  PasswordMailer.with(<%= singular_table_name %>: self).changed.deliver_later
22
22
  end
23
23
  end
24
-
25
- <% if options.api? -%>
24
+ <% if options.api? %>
26
25
  def signed_session_token
27
- self.class.signed_id_verifier.generate(session_token)
26
+ Rails.application.message_verifier(:session_token).generate(session_token)
28
27
  end
29
28
 
30
29
  def self.find_signed_session_token(signed_session_token)
31
- if session_token = signed_id_verifier.verified(signed_session_token)
30
+ if session_token = Rails.application.message_verifier(:session_token).verified(signed_session_token)
32
31
  find_by_session_token(session_token)
33
32
  end
34
33
  end
34
+
35
+ def as_json(options = {})
36
+ super(options.merge(except: [:password_digest, :session_token]))
37
+ end
35
38
  <% end -%>
36
39
  end
@@ -0,0 +1,20 @@
1
+ require "test_helper"
2
+
3
+ class CancellationsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "should create cancellation" do
9
+ assert_difference("<%= class_name %>.count", -1) do
10
+ post cancellations_url, headers: { "Authorization" => "Bearer #{@token}" }
11
+ end
12
+
13
+ assert_response :no_content
14
+ end
15
+
16
+ def sign_in_as(<%= singular_table_name %>)
17
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
18
+ [<%= singular_table_name %>, response.parsed_body["session_token"]]
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ class EmailsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
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
+
13
+ assert_response :success
14
+ end
15
+
16
+ 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
20
+
21
+ assert_response :bad_request
22
+ assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
23
+ end
24
+
25
+ def sign_in_as(<%= singular_table_name %>)
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
+ [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ require "test_helper"
2
+
3
+ class PasswordResetsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
+ @sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
8
+ end
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
+ test "should send a password reset email" do
18
+ assert_enqueued_email_with PasswordMailer, :reset, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
19
+ post password_resets_url, params: { email: @<%= singular_table_name %>.email }
20
+ end
21
+
22
+ assert_response :no_content
23
+ end
24
+
25
+ test "should not send a password reset email to a nonexistent email" do
26
+ assert_no_enqueued_emails do
27
+ post password_resets_url, params: { email: "invalid_email@hey.com" }
28
+ end
29
+
30
+ assert_response :not_found
31
+ assert_equal "The email address doesn't exist in our database", response.parsed_body["error"]
32
+ end
33
+
34
+ test "should update password" do
35
+ patch password_resets_url, params: { token: @sid, password: "new_password", password_confirmation: "new_password" }
36
+
37
+ assert_response :success
38
+ end
39
+
40
+ test "should not update password with expired token" do
41
+ patch password_resets_url, params: { token: @sid_exp, password: "new_password", password_confirmation: "new_password" }
42
+
43
+ assert_response :bad_request
44
+ assert_equal "Your token has expired, please request a new one", response.parsed_body["error"]
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ class PasswordsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %>, @token = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
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
+
13
+ assert_response :success
14
+ end
15
+
16
+ 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
20
+
21
+ assert_response :bad_request
22
+ assert_equal "The current password you entered is incorrect", response.parsed_body["error"]
23
+ end
24
+
25
+ def sign_in_as(<%= singular_table_name %>)
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
+ [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ require "test_helper"
2
+
3
+ class RegistrationsControllerTest < ActionDispatch::IntegrationTest
4
+ test "should sign up" do
5
+ assert_difference("<%= class_name %>.count") do
6
+ post sign_up_url, params: { email: "lazaronixon@hey.com", password: "secret123", password_confirmation: "secret123" }
7
+ end
8
+
9
+ assert_response :created
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ class SessionsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ end
7
+
8
+ test "should sign in" do
9
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "secret123" }
10
+ assert_response :success
11
+ end
12
+
13
+ test "should not sign in with wrong credentials" do
14
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "wrong_password" }
15
+ assert_response :unauthorized
16
+ end
17
+
18
+ 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}" }
22
+ assert_response :no_content
23
+ end
24
+
25
+ def sign_in_as(<%= singular_table_name %>)
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" })
27
+ [<%= singular_table_name %>, response.parsed_body["session_token"]]
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ require "test_helper"
2
+
3
+ class CancellationsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "should get new" do
9
+ get new_cancellations_url
10
+ assert_response :success
11
+ end
12
+
13
+ test "should create cancellation" do
14
+ assert_difference("<%= class_name %>.count", -1) do
15
+ post cancellations_url
16
+ end
17
+
18
+ assert_redirected_to sign_in_url
19
+ end
20
+
21
+ def sign_in_as(<%= singular_table_name %>)
22
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require "test_helper"
2
+
3
+ class EmailsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "should get edit" do
9
+ get edit_emails_url
10
+ assert_response :success
11
+ end
12
+
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
+
18
+ assert_redirected_to root_path
19
+ end
20
+
21
+ 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
25
+
26
+ assert_redirected_to edit_emails_path
27
+ assert_equal "The current password you entered is incorrect", flash[:alert]
28
+ end
29
+
30
+ def sign_in_as(<%= singular_table_name %>)
31
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
32
+ end
33
+ end
@@ -0,0 +1,49 @@
1
+ require "test_helper"
2
+
3
+ class PasswordResetsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
+ @sid_exp = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 0.minutes)
8
+ end
9
+
10
+ test "should get new" do
11
+ get new_password_resets_url
12
+ assert_response :success
13
+ end
14
+
15
+ test "should get edit" do
16
+ get edit_password_resets_url(token: @sid)
17
+ assert_response :success
18
+ end
19
+
20
+ test "should send a password reset email" do
21
+ assert_enqueued_email_with PasswordMailer, :reset, args: { <%= singular_table_name %>: @<%= singular_table_name %> } do
22
+ post password_resets_url, params: { email: @<%= singular_table_name %>.email }
23
+ end
24
+
25
+ assert_redirected_to sign_in_path
26
+ end
27
+
28
+ test "should not send a password reset email to a nonexistent email" do
29
+ assert_no_enqueued_emails do
30
+ post password_resets_url, params: { email: "invalid_email@hey.com" }
31
+ end
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]
35
+ end
36
+
37
+ test "should update password" do
38
+ patch password_resets_url, params: { token: @sid, <%= singular_table_name %>: { password: "new_password", password_confirmation: "new_password" } }
39
+
40
+ assert_redirected_to sign_in_path
41
+ end
42
+
43
+ test "should not update password with expired token" do
44
+ patch password_resets_url, params: { token: @sid_exp, password: "new_password", password_confirmation: "new_password" }
45
+
46
+ assert_redirected_to new_password_resets_path
47
+ assert_equal "Your token has expired, please request a new one", flash[:alert]
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ require "test_helper"
2
+
3
+ class PasswordsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "should get edit" do
9
+ get edit_passwords_url
10
+ assert_response :success
11
+ end
12
+
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
+
18
+ assert_redirected_to root_path
19
+ end
20
+
21
+ 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
25
+
26
+ assert_redirected_to edit_passwords_path
27
+ assert_equal "The current password you entered is incorrect", flash[:alert]
28
+ end
29
+
30
+ def sign_in_as(<%= singular_table_name %>)
31
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ require "test_helper"
2
+
3
+ class RegistrationsControllerTest < ActionDispatch::IntegrationTest
4
+ test "should get new" do
5
+ get sign_up_url
6
+ assert_response :success
7
+ end
8
+
9
+ test "should sign up" do
10
+ assert_difference("<%= class_name %>.count") do
11
+ post sign_up_url, params: { <%= singular_table_name %>: { email: "lazaronixon@hey.com", password: "secret123", password_confirmation: "secret123" } }
12
+ end
13
+ assert_redirected_to root_url
14
+
15
+ follow_redirect!
16
+ assert_response :success
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ require "test_helper"
2
+
3
+ class SessionsControllerTest < ActionDispatch::IntegrationTest
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ end
7
+
8
+ test "should get new" do
9
+ get sign_in_url
10
+ assert_response :success
11
+ end
12
+
13
+ test "should sign in" do
14
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "secret123" }
15
+ assert_redirected_to root_url
16
+
17
+ get root_url
18
+ assert_response :success
19
+ end
20
+
21
+ test "should not sign in with wrong credentials" do
22
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "wrong_password" }
23
+ assert_redirected_to sign_in_url(email_hint: @<%= singular_table_name %>.email)
24
+ assert_equal "Invalid email or password", flash[:alert]
25
+
26
+ get root_url
27
+ assert_redirected_to sign_in_path
28
+ assert_equal "You need to sign in or sign up before continuing", flash[:alert]
29
+ end
30
+
31
+ test "should sign out" do
32
+ sign_in_as @<%= singular_table_name %>
33
+
34
+ delete sign_out_url
35
+ assert_redirected_to sign_in_path
36
+
37
+ get root_path
38
+ assert_redirected_to sign_in_path
39
+ assert_equal "You need to sign in or sign up before continuing", flash[:alert]
40
+ end
41
+
42
+ def sign_in_as(<%= singular_table_name %>)
43
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "secret123" }); user
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
+
3
+ lazaro_nixon:
4
+ email: lazaronixon@hotmail.com
5
+ password_digest: <%%= BCrypt::Password.create("secret123") %>
6
+ session_token: <%%= SecureRandom.base58(24) %>
@@ -0,0 +1,23 @@
1
+ require "application_system_test_case"
2
+
3
+ class CancellationsTest < ApplicationSystemTestCase
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "cancelling my account" do
9
+ click_on "Cancel my account & delete my data"
10
+ click_on "OK, close my account"
11
+
12
+ assert_text "Bye! Your account has been successfully cancelled"
13
+ end
14
+
15
+ def sign_in_as(<%= singular_table_name %>)
16
+ visit sign_in_url
17
+ fill_in :email, with: <%= singular_table_name %>.email
18
+ fill_in :password, with: "secret123"
19
+ click_on "Sign in"
20
+
21
+ return <%= singular_table_name %>
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ require "application_system_test_case"
2
+
3
+ class EmailsTest < ApplicationSystemTestCase
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "updating the email" do
9
+ click_on "Change email"
10
+
11
+ fill_in "Current password", with: "secret123"
12
+ fill_in "New email", with: "new_email@hey.com"
13
+ click_on "Save changes"
14
+
15
+ assert_text "Your email has been changed successfully"
16
+ end
17
+
18
+ def sign_in_as(<%= singular_table_name %>)
19
+ visit sign_in_url
20
+ fill_in :email, with: <%= singular_table_name %>.email
21
+ fill_in :password, with: "secret123"
22
+ click_on "Sign in"
23
+
24
+ return <%= singular_table_name %>
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ require "application_system_test_case"
2
+
3
+ class PasswordResetsTest < ApplicationSystemTestCase
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ @sid = @<%= singular_table_name %>.signed_id(purpose: :password_reset, expires_in: 20.minutes)
7
+ end
8
+
9
+ test "sending a password reset email" do
10
+ visit sign_in_url
11
+ click_on "Forgot your password?"
12
+
13
+ fill_in "Email", with: @<%= singular_table_name %>.email
14
+ click_on "Send password reset email"
15
+
16
+ assert_text "You will receive an email with instructions on how to reset your password in a few minutes"
17
+ end
18
+
19
+ test "updating password" do
20
+ visit edit_password_resets_url(token: @sid)
21
+
22
+ fill_in "New password", with: "new_password"
23
+ fill_in "Confirm new password", with: "new_password"
24
+ click_on "Save changes"
25
+
26
+ assert_text "Your password was reset successfully. Please sign in"
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ require "application_system_test_case"
2
+
3
+ class PasswordsTest < ApplicationSystemTestCase
4
+ setup do
5
+ @<%= singular_table_name %> = sign_in_as(<%= table_name %>(:lazaro_nixon))
6
+ end
7
+
8
+ test "updating the password" do
9
+ click_on "Change password"
10
+
11
+ fill_in "Current password", with: "secret123"
12
+ fill_in "New password", with: "new_password"
13
+ fill_in "Confirm new password", with: "new_password"
14
+ click_on "Save changes"
15
+
16
+ assert_text "Your password has been changed successfully"
17
+ end
18
+
19
+ def sign_in_as(<%= singular_table_name %>)
20
+ visit sign_in_url
21
+ fill_in :email, with: <%= singular_table_name %>.email
22
+ fill_in :password, with: "secret123"
23
+ click_on "Sign in"
24
+
25
+ return <%= singular_table_name %>
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ require "application_system_test_case"
2
+
3
+ class RegistrationsTest < ApplicationSystemTestCase
4
+ test "signing up" do
5
+ visit sign_in_url
6
+ click_on "Sign up"
7
+
8
+ fill_in "Email", with: "lazaronixon@hey.com"
9
+ fill_in "Password", with: "new_password"
10
+ fill_in "Password confirmation", with: "new_password"
11
+ click_on "Sign up"
12
+
13
+ assert_text "Welcome! You have signed up successfully"
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ require "application_system_test_case"
2
+
3
+ class SessionsTest < ApplicationSystemTestCase
4
+ setup do
5
+ @<%= singular_table_name %> = <%= table_name %>(:lazaro_nixon)
6
+ end
7
+
8
+ test "signing in" do
9
+ visit sign_in_url
10
+ fill_in "Email", with: @<%= singular_table_name %>.email
11
+ fill_in "Password", with: "secret123"
12
+ click_on "Sign in"
13
+
14
+ assert_text "Signed in successfully"
15
+ end
16
+
17
+ test "signing out" do
18
+ sign_in_as @<%= singular_table_name %>
19
+
20
+ click_on "Log out"
21
+ assert_text "Signed out successfully"
22
+ end
23
+
24
+ def sign_in_as(<%= singular_table_name %>)
25
+ visit sign_in_url
26
+ fill_in :email, with: <%= singular_table_name %>.email
27
+ fill_in :password, with: "secret123"
28
+ click_on "Sign in"
29
+
30
+ return <%= singular_table_name %>
31
+ end
32
+ end
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: 0.0.22
4
+ version: 1.0.1
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-19 00:00:00.000000000 Z
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -43,24 +43,42 @@ files:
43
43
  - lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt
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
+ - 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
+ - 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
+ - lib/generators/authentication/templates/erb/password_mailer/reset.html.erb.tt
53
+ - lib/generators/authentication/templates/erb/password_mailer/reset.text.erb.tt
54
+ - lib/generators/authentication/templates/erb/password_resets/edit.html.erb.tt
55
+ - lib/generators/authentication/templates/erb/password_resets/new.html.erb.tt
56
+ - lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt
57
+ - lib/generators/authentication/templates/erb/registrations/new.html.erb.tt
58
+ - lib/generators/authentication/templates/erb/sessions/new.html.erb.tt
46
59
  - lib/generators/authentication/templates/mailers/email_mailer.rb.tt
47
60
  - lib/generators/authentication/templates/mailers/password_mailer.rb.tt
48
- - lib/generators/authentication/templates/migration.rb.tt
49
61
  - lib/generators/authentication/templates/models/current.rb.tt
50
- - lib/generators/authentication/templates/models/resource.rb.tt
51
- - lib/generators/authentication/templates/views/cancellations/new.html.erb.tt
52
- - lib/generators/authentication/templates/views/email_mailer/changed.html.erb.tt
53
- - lib/generators/authentication/templates/views/email_mailer/changed.text.erb.tt
54
- - lib/generators/authentication/templates/views/emails/edit.html.erb.tt
55
- - lib/generators/authentication/templates/views/password_mailer/changed.html.erb.tt
56
- - lib/generators/authentication/templates/views/password_mailer/changed.text.erb.tt
57
- - lib/generators/authentication/templates/views/password_mailer/reset.html.erb.tt
58
- - lib/generators/authentication/templates/views/password_mailer/reset.text.erb.tt
59
- - lib/generators/authentication/templates/views/password_resets/edit.html.erb.tt
60
- - lib/generators/authentication/templates/views/password_resets/new.html.erb.tt
61
- - lib/generators/authentication/templates/views/passwords/edit.html.erb.tt
62
- - lib/generators/authentication/templates/views/registrations/new.html.erb.tt
63
- - lib/generators/authentication/templates/views/sessions/new.html.erb.tt
62
+ - lib/generators/authentication/templates/models/model.rb.tt
63
+ - lib/generators/authentication/templates/test_unit/controllers/api/cancellations_controller_test.rb.tt
64
+ - lib/generators/authentication/templates/test_unit/controllers/api/emails_controller_test.rb.tt
65
+ - lib/generators/authentication/templates/test_unit/controllers/api/password_resets_controller_test.rb.tt
66
+ - lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt
67
+ - lib/generators/authentication/templates/test_unit/controllers/api/registrations_controller_test.rb.tt
68
+ - lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt
69
+ - lib/generators/authentication/templates/test_unit/controllers/html/cancellations_controller_test.rb.tt
70
+ - lib/generators/authentication/templates/test_unit/controllers/html/emails_controller_test.rb.tt
71
+ - lib/generators/authentication/templates/test_unit/controllers/html/password_resets_controller_test.rb.tt
72
+ - lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt
73
+ - lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt
74
+ - lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt
75
+ - lib/generators/authentication/templates/test_unit/fixtures.yml.tt
76
+ - lib/generators/authentication/templates/test_unit/system/cancellations_test.rb.tt
77
+ - lib/generators/authentication/templates/test_unit/system/emails_test.rb.tt
78
+ - lib/generators/authentication/templates/test_unit/system/password_resets_test.rb.tt
79
+ - lib/generators/authentication/templates/test_unit/system/passwords_test.rb.tt
80
+ - lib/generators/authentication/templates/test_unit/system/registrations_test.rb.tt
81
+ - lib/generators/authentication/templates/test_unit/system/sessions_test.rb.tt
64
82
  homepage: https://github.com/lazaronixon/authentication-zero
65
83
  licenses:
66
84
  - MIT
@@ -1,14 +0,0 @@
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
- t.string :session_token, null: false
7
-
8
- t.timestamps
9
- end
10
-
11
- add_index :<%= table_name %>, :email, unique: true
12
- add_index :<%= table_name %>, :session_token, unique: true
13
- end
14
- end