authentication-zero 2.8.2 → 2.9.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -0
  5. data/lib/authentication_zero/version.rb +1 -1
  6. data/lib/generators/authentication/authentication_generator.rb +49 -20
  7. data/lib/generators/authentication/templates/controllers/api/authentications/events_controller.rb.tt +5 -0
  8. data/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt +1 -5
  9. data/lib/generators/authentication/templates/controllers/html/authentications/events_controller.rb.tt +5 -0
  10. data/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +1 -1
  11. data/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt +1 -1
  12. data/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt +1 -1
  13. data/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt +2 -6
  14. data/lib/generators/authentication/templates/controllers/{omniauth_controller.rb.tt → html/sessions/omniauth_controller.rb.tt} +1 -5
  15. data/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt +1 -1
  16. data/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +1 -5
  17. data/lib/generators/authentication/templates/erb/authentications/events/index.html.erb +33 -0
  18. data/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +1 -1
  19. data/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt +1 -1
  20. data/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt +1 -1
  21. data/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt +1 -1
  22. data/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +1 -1
  23. data/lib/generators/authentication/templates/migrations/create_events_migration.rb.tt +12 -0
  24. data/lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt +2 -2
  25. data/lib/generators/authentication/templates/migrations/create_table_migration.rb.tt +7 -0
  26. data/lib/generators/authentication/templates/models/current.rb.tt +1 -0
  27. data/lib/generators/authentication/templates/models/event.rb.tt +8 -0
  28. data/lib/generators/authentication/templates/models/model.rb.tt +16 -4
  29. data/lib/generators/authentication/templates/models/session.rb.tt +15 -0
  30. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/email_verifications_controller_test.rb.tt +1 -1
  31. data/lib/generators/authentication/templates/test_unit/controllers/api/identity/emails_controller_test.rb.tt +1 -1
  32. data/lib/generators/authentication/templates/test_unit/controllers/api/passwords_controller_test.rb.tt +1 -1
  33. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions/sudos_controller_test.rb.tt +1 -1
  34. data/lib/generators/authentication/templates/test_unit/controllers/api/sessions_controller_test.rb.tt +3 -3
  35. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/email_verifications_controller_test.rb.tt +1 -1
  36. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/emails_controller_test.rb.tt +3 -3
  37. data/lib/generators/authentication/templates/test_unit/controllers/html/identity/password_resets_controller_test.rb.tt +1 -1
  38. data/lib/generators/authentication/templates/test_unit/controllers/html/passwords_controller_test.rb.tt +3 -3
  39. data/lib/generators/authentication/templates/test_unit/controllers/html/registrations_controller_test.rb.tt +1 -1
  40. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions/sudos_controller_test.rb.tt +1 -1
  41. data/lib/generators/authentication/templates/test_unit/controllers/html/sessions_controller_test.rb.tt +3 -3
  42. metadata +8 -4
  43. data/lib/generators/authentication/templates/migrations/add_omniauth_migration.rb.tt +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ea407810dad8ddf7ac7366ebf6fe46c7d3558b2376fc33981ecb5ee32d968f0
4
- data.tar.gz: 9be562630186a350cb34df5d395692b99219f5627568a19715d3c826b706cffa
3
+ metadata.gz: 17c277204408ebec113d5e006bec8407d237756e4f86c67dae7a0e01c4a1c0de
4
+ data.tar.gz: 87c2e57c9035847f84abc12b1c4f0a7350c4a010cd9c6fc8442d9c229b646af7
5
5
  SHA512:
6
- metadata.gz: 1e08a25cda16b7e975057159b8cafac1a9e20a94730c5a28a10f9b5d26a66d448895e2b726141a1f6091042e2ffc31c730bcae0ca9d7609b0b5cde5b3bb5ae7d
7
- data.tar.gz: 4c00dd86cea638d791c1306114405cac87c7703aa615e730be5fb6719293b0c76fd83ec905cc7043af0e282605240ccab85225167db7e2aa6cba6a2d576ff570
6
+ metadata.gz: 2bb208d31c2d4a5d9af479253f39db98e5c2182796a74debb06aeadcdec22547abd29b90a6f440cca29405ef2110937d2a5185085f3f321acd705d409ec65b16
7
+ data.tar.gz: f36f9a8791f1bcb6b821c69694b416481aa3811383f55027362e9a92cd3e1aea11436aab998b50eea620b089a84ee05fa88725732fa087bf570794c105085ba6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## Authentication Zero 2.9.0 (March 2, 2022) ##
2
+
3
+ * Implement trackable
4
+
1
5
  ## Authentication Zero 2.8.0 (March 2, 2022) ##
2
6
 
3
7
  * Organize controllers in identity and sessions namespaces
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authentication-zero (2.8.2)
4
+ authentication-zero (2.9.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -20,6 +20,7 @@ The purpose of authentication zero is to generate a pre-built authentication sys
20
20
  - Send e-mail confirmation when your email has been changed
21
21
  - Send e-mail notification when someone has logged into your account
22
22
  - Manage multiple sessions & devices
23
+ - Activity log (--trackable)
23
24
  - Log out
24
25
 
25
26
  ## Security and best practices
@@ -1,3 +1,3 @@
1
1
  module AuthenticationZero
2
- VERSION = "2.8.2"
2
+ VERSION = "2.9.0"
3
3
  end
@@ -8,6 +8,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
8
8
  class_option :lockable, type: :boolean, desc: "Add password reset locking"
9
9
  class_option :ratelimit, type: :boolean, desc: "Add request rate limiting"
10
10
  class_option :omniauthable, type: :boolean, desc: "Add social login support"
11
+ class_option :trackable, type: :boolean, desc: "Add activity log support"
11
12
 
12
13
  source_root File.expand_path("templates", __dir__)
13
14
 
@@ -47,7 +48,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
47
48
  def create_migrations
48
49
  migration_template "migrations/create_table_migration.rb", "#{db_migrate_path}/create_#{table_name}.rb"
49
50
  migration_template "migrations/create_sessions_migration.rb", "#{db_migrate_path}/create_sessions.rb"
50
- migration_template "migrations/add_omniauth_migration.rb", "#{db_migrate_path}/add_omniauth_to_#{table_name}.rb" if omniauthable?
51
+ migration_template "migrations/create_events_migration.rb", "#{db_migrate_path}/create_events.rb" if options.trackable?
51
52
  end
52
53
 
53
54
  def create_models
@@ -55,6 +56,7 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
55
56
  template "models/session.rb", "app/models/session.rb"
56
57
  template "models/current.rb", "app/models/current.rb"
57
58
  template "models/locking.rb", "app/models/locking.rb" if options.lockable?
59
+ template "models/event.rb", "app/models/event.rb" if options.trackable?
58
60
  end
59
61
 
60
62
  def create_fixture_file
@@ -65,39 +67,53 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
65
67
  api_code = <<~CODE
66
68
  include ActionController::HttpAuthentication::Token::ControllerMethods
67
69
 
70
+ before_action :set_current_request_details
68
71
  before_action :authenticate
69
72
 
70
- def authenticate
71
- if session = authenticate_with_http_token { |token, _| Session.find_signed(token) }
72
- Current.session = session
73
- else
74
- request_http_token_authentication
75
- end
76
- end
77
-
78
73
  def require_sudo
79
74
  if Current.session.sudo_at < 30.minutes.ago
80
75
  render json: { error: "Enter your password to continue" }, status: :forbidden
81
76
  end
82
77
  end
78
+
79
+ private
80
+ def authenticate
81
+ if session = authenticate_with_http_token { |token, _| Session.find_signed(token) }
82
+ Current.session = session
83
+ else
84
+ request_http_token_authentication
85
+ end
86
+ end
87
+
88
+ def set_current_request_details
89
+ Current.user_agent = request.user_agent
90
+ Current.ip_address = request.ip
91
+ end
83
92
  CODE
84
93
 
85
94
  html_code = <<~CODE
95
+ before_action :set_current_request_details
86
96
  before_action :authenticate
87
97
 
88
- def authenticate
89
- if session = Session.find_by_id(cookies.signed[:session_token])
90
- Current.session = session
91
- else
92
- redirect_to sign_in_path
93
- end
94
- end
95
-
96
98
  def require_sudo
97
99
  if Current.session.sudo_at < 30.minutes.ago
98
100
  redirect_to new_sessions_sudo_path(proceed_to_url: request.url)
99
101
  end
100
102
  end
103
+
104
+ private
105
+ def authenticate
106
+ if session = Session.find_by_id(cookies.signed[:session_token])
107
+ Current.session = session
108
+ else
109
+ redirect_to sign_in_path
110
+ end
111
+ end
112
+
113
+ def set_current_request_details
114
+ Current.user_agent = request.user_agent
115
+ Current.ip_address = request.ip
116
+ end
101
117
  CODE
102
118
 
103
119
  inject_code = options.api? ? api_code : html_code
@@ -105,8 +121,13 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
105
121
  end
106
122
 
107
123
  def create_controllers
108
- directory "controllers/#{format_folder}", "app/controllers"
109
- template "controllers/omniauth_controller.rb", "app/controllers/sessions/omniauth_controller.rb" if omniauthable?
124
+ directory "controllers/#{format_folder}/identity", "app/controllers/identity"
125
+ template "controllers/#{format_folder}/passwords_controller.rb", "app/controllers/passwords_controller.rb"
126
+ template "controllers/#{format_folder}/registrations_controller.rb", "app/controllers/registrations_controller.rb"
127
+ template "controllers/#{format_folder}/sessions_controller.rb", "app/controllers/sessions_controller.rb"
128
+ template "controllers/#{format_folder}/sessions/sudos_controller.rb", "app/controllers/sessions/sudos_controller.rb"
129
+ template "controllers/#{format_folder}/sessions/omniauth_controller.rb", "app/controllers/sessions/omniauth_controller.rb" if omniauthable?
130
+ template "controllers/#{format_folder}/authentications/events_controller.rb", "app/controllers/authentications/events_controller.rb" if options.trackable?
110
131
  end
111
132
 
112
133
  def create_views
@@ -114,7 +135,11 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
114
135
  directory "erb/identity_mailer", "app/views/identity_mailer"
115
136
  directory "erb/session_mailer", "app/views/session_mailer"
116
137
  else
117
- directory "erb", "app/views"
138
+ directory "erb/identity", "app/views/identity"
139
+ directory "erb/passwords", "app/views/passwords"
140
+ directory "erb/registrations", "app/views/registrations"
141
+ directory "erb/sessions", "app/views/sessions"
142
+ directory "erb/authentications/events", "app/views/authentications/events" if options.trackable?
118
143
  end
119
144
  end
120
145
 
@@ -129,6 +154,10 @@ class AuthenticationGenerator < Rails::Generators::NamedBase
129
154
  route "get '/auth/failure', to: 'sessions/omniauth#failure'"
130
155
  end
131
156
 
157
+ if options.trackable?
158
+ route "resources :events, only: :index", namespace: :authentications
159
+ end
160
+
132
161
  route "resource :password_reset, only: [:new, :edit, :create, :update]", namespace: :identity
133
162
  route "resource :email_verification, only: [:edit, :create]", namespace: :identity
134
163
  route "resource :email, only: [:edit, :update]", namespace: :identity
@@ -0,0 +1,5 @@
1
+ class Authentications::EventsController < ApplicationController
2
+ def index
3
+ render json: Current.<%= singular_table_name %>.events.order(created_at: :desc)
4
+ end
5
+ end
@@ -15,7 +15,7 @@ class SessionsController < ApplicationController
15
15
  <%= singular_table_name %> = <%= class_name %>.find_by(email: params[:email])
16
16
 
17
17
  if <%= singular_table_name %> && <%= singular_table_name %>.authenticate(params[:password])
18
- @session = <%= singular_table_name %>.sessions.create!(session_params)
18
+ @session = <%= singular_table_name %>.sessions.create!
19
19
  response.set_header("X-Session-Token", @session.signed_id)
20
20
 
21
21
  render json: @session, status: :created
@@ -32,8 +32,4 @@ class SessionsController < ApplicationController
32
32
  def set_session
33
33
  @session = Current.<%= singular_table_name %>.sessions.find(params[:id])
34
34
  end
35
-
36
- def session_params
37
- { user_agent: request.user_agent, ip_address: request.remote_ip, sudo_at: Time.current }
38
- end
39
35
  end
@@ -0,0 +1,5 @@
1
+ class Authentications::EventsController < ApplicationController
2
+ def index
3
+ @events = Current.<%= singular_table_name %>.events.order(created_at: :desc)
4
+ end
5
+ end
@@ -19,6 +19,6 @@ class Identity::EmailsController < ApplicationController
19
19
  end
20
20
 
21
21
  def <%= "#{singular_table_name}_params" %>
22
- params.require(:<%= singular_table_name %>).permit(:email)
22
+ params.permit(:email)
23
23
  end
24
24
  end
@@ -37,7 +37,7 @@ class Identity::PasswordResetsController < ApplicationController
37
37
  end
38
38
 
39
39
  def <%= "#{singular_table_name}_params" %>
40
- params.require(:<%= singular_table_name %>).permit(:password, :password_confirmation)
40
+ params.permit(:password, :password_confirmation)
41
41
  end
42
42
  <% if options.lockable? %>
43
43
  def require_locking
@@ -20,6 +20,6 @@ class PasswordsController < ApplicationController
20
20
  end
21
21
 
22
22
  def <%= "#{singular_table_name}_params" %>
23
- params.require(:<%= singular_table_name %>).permit(:password, :password_confirmation)
23
+ params.permit(:password, :password_confirmation)
24
24
  end
25
25
  end
@@ -9,7 +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
- session = @<%= singular_table_name %>.sessions.create!(session_params)
12
+ session = @<%= singular_table_name %>.sessions.create!
13
13
  cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
14
14
 
15
15
  redirect_to root_path, notice: "Welcome! You have signed up successfully"
@@ -20,10 +20,6 @@ class RegistrationsController < ApplicationController
20
20
 
21
21
  private
22
22
  def <%= "#{singular_table_name}_params" %>
23
- params.require(:<%= singular_table_name %>).permit(:email, :password, :password_confirmation)
24
- end
25
-
26
- def session_params
27
- { user_agent: request.user_agent, ip_address: request.remote_ip, sudo_at: Time.current }
23
+ params.permit(:email, :password, :password_confirmation)
28
24
  end
29
25
  end
@@ -6,7 +6,7 @@ class Sessions::OmniauthController < ApplicationController
6
6
  @<%= singular_table_name %> = <%= class_name %>.where(omniauth_params).first_or_initialize(<%= "#{singular_table_name}_params" %>)
7
7
 
8
8
  if @<%= singular_table_name %>.save
9
- session = @<%= singular_table_name %>.sessions.create!(session_params)
9
+ session = @<%= singular_table_name %>.sessions.create!
10
10
  cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
11
11
 
12
12
  redirect_to root_path, notice: "Signed in successfully"
@@ -28,10 +28,6 @@ class Sessions::OmniauthController < ApplicationController
28
28
  { email: omniauth.info.email, password: SecureRandom::base58, verified: true }
29
29
  end
30
30
 
31
- def session_params
32
- { user_agent: request.user_agent, ip_address: request.remote_ip, sudo_at: Time.current }
33
- end
34
-
35
31
  def omniauth
36
32
  request.env["omniauth.auth"]
37
33
  end
@@ -5,7 +5,7 @@ class Sessions::SudosController < ApplicationController
5
5
  def create
6
6
  session = Current.session
7
7
 
8
- <% if options.omniauth? -%>
8
+ <% if omniauthable? -%>
9
9
  if session.<%= singular_table_name %>.authenticate(params[:password]) || session.<%= singular_table_name %>.provider
10
10
  <% else -%>
11
11
  if session.<%= singular_table_name %>.authenticate(params[:password])
@@ -15,7 +15,7 @@ class SessionsController < ApplicationController
15
15
  <%= singular_table_name %> = <%= class_name %>.find_by(email: params[:email])
16
16
 
17
17
  if <%= singular_table_name %> && <%= singular_table_name %>.authenticate(params[:password])
18
- @session = <%= singular_table_name %>.sessions.create!(session_params)
18
+ @session = <%= singular_table_name %>.sessions.create!
19
19
  cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
20
20
 
21
21
  redirect_to root_path, notice: "Signed in successfully"
@@ -32,8 +32,4 @@ class SessionsController < ApplicationController
32
32
  def set_session
33
33
  @session = Current.<%= singular_table_name %>.sessions.find(params[:id])
34
34
  end
35
-
36
- def session_params
37
- { user_agent: request.user_agent, ip_address: request.remote_ip, sudo_at: Time.current }
38
- end
39
35
  end
@@ -0,0 +1,33 @@
1
+ <h1>Activity Log</h1>
2
+
3
+ <div id="sessions">
4
+ <% @events.each do |event| %>
5
+ <div id="<%= dom_id event %>">
6
+ <p>
7
+ <strong>User Agent:</strong>
8
+ <%= event.user_agent %>
9
+ </p>
10
+
11
+ <p>
12
+ <strong>Action:</strong>
13
+ <%= event.action %>
14
+ </p>
15
+
16
+ <p>
17
+ <strong>Ip Address:</strong>
18
+ <%= event.ip_address %>
19
+ </p>
20
+
21
+ <p>
22
+ <strong>Created at:</strong>
23
+ <%= event.created_at %>
24
+ </p>
25
+ </div>
26
+ <% end %>
27
+ </div>
28
+
29
+ <br>
30
+
31
+ <div>
32
+ <%= link_to "Back", root_path %>
33
+ </div>
@@ -8,7 +8,7 @@
8
8
  <p><%%= button_to "Re-send verification email", identity_email_verification_path %></p>
9
9
  <%% end %>
10
10
 
11
- <%%= form_with(model: @<%= model_resource_name %>, url: identity_email_path) do |form| %>
11
+ <%%= form_with(url: identity_email_path, method: :patch) do |form| %>
12
12
  <%% if @<%= singular_table_name %>.errors.any? %>
13
13
  <div style="color: red">
14
14
  <h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
@@ -1,6 +1,6 @@
1
1
  <h1>Reset your password</h1>
2
2
 
3
- <%%= form_with(model: @<%= model_resource_name %>, url: identity_password_reset_path) do |form| %>
3
+ <%%= form_with(url: identity_password_reset_path, method: :patch) do |form| %>
4
4
  <%% if @<%= singular_table_name %>.errors.any? %>
5
5
  <div style="color: red">
6
6
  <h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
@@ -2,7 +2,7 @@
2
2
 
3
3
  <h1>Change your password</h1>
4
4
 
5
- <%%= form_with(model: @<%= model_resource_name %>, url: password_path) do |form| %>
5
+ <%%= form_with(url: password_path, method: :patch) do |form| %>
6
6
  <%% if @<%= singular_table_name %>.errors.any? %>
7
7
  <div style="color: red">
8
8
  <h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
@@ -1,6 +1,6 @@
1
1
  <h1>Sign up</h1>
2
2
 
3
- <%%= form_with(model: @<%= model_resource_name %>, url: sign_up_path) do |form| %>
3
+ <%%= form_with(url: sign_up_path) do |form| %>
4
4
  <%% if @<%= singular_table_name %>.errors.any? %>
5
5
  <div style="color: red">
6
6
  <h2><%%= pluralize(@<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
@@ -18,7 +18,7 @@
18
18
  <%%= form.submit "Sign in" %>
19
19
  </div>
20
20
  <%% end %>
21
- <% if options.omniauth? %>
21
+ <% if omniauthable? %>
22
22
  <div>
23
23
  <%%= button_to "Sign in with OmniAuth", "/auth/developer", "data-turbo" => false %>
24
24
  </div>
@@ -0,0 +1,12 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :events do |t|
4
+ t.references :<%= singular_table_name %>, null: false, foreign_key: true
5
+ t.string :action, null: false
6
+ t.string :user_agent
7
+ t.string :ip_address
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -3,8 +3,8 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
3
3
  create_table :sessions do |t|
4
4
  t.references :<%= singular_table_name %>, null: false, foreign_key: true
5
5
 
6
- t.string :user_agent, null: false
7
- t.string :ip_address, null: false
6
+ t.string :user_agent
7
+ t.string :ip_address
8
8
 
9
9
  t.datetime :sudo_at, null: false
10
10
 
@@ -5,10 +5,17 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
5
5
  t.string :password_digest, null: false
6
6
 
7
7
  t.boolean :verified, null: false, default: false
8
+ <% if omniauthable? %>
9
+ t.string :provider
10
+ t.string :uid
11
+ <% end -%>
8
12
 
9
13
  t.timestamps
10
14
  end
11
15
 
12
16
  add_index :<%= table_name %>, :email, unique: true
17
+ <% if omniauthable? -%>
18
+ add_index :<%= table_name %>, [:provider, :uid], unique: true
19
+ <% end -%>
13
20
  end
14
21
  end
@@ -1,5 +1,6 @@
1
1
  class Current < ActiveSupport::CurrentAttributes
2
2
  attribute :session, :<%= singular_table_name %>
3
+ attribute :user_agent, :ip_address
3
4
 
4
5
  def session=(session)
5
6
  super; self.<%= singular_table_name %> = session.<%= singular_table_name %>
@@ -0,0 +1,8 @@
1
+ class Event < ApplicationRecord
2
+ belongs_to :<%= singular_table_name %>
3
+
4
+ before_create do
5
+ self.user_agent = Current.user_agent
6
+ self.ip_address = Current.ip_address
7
+ end
8
+ end
@@ -2,6 +2,9 @@ class <%= class_name %> < ApplicationRecord
2
2
  has_secure_password
3
3
 
4
4
  has_many :sessions, dependent: :destroy
5
+ <% if options.trackable? -%>
6
+ has_many :events, dependent: :destroy
7
+ <% end -%>
5
8
 
6
9
  validates :email, presence: true, uniqueness: true
7
10
  validates_format_of :email, with: /\A[^@\s]+@[^@\s]+\z/
@@ -24,11 +27,20 @@ class <%= class_name %> < ApplicationRecord
24
27
  sessions.where.not(id: Current.session).destroy_all
25
28
  end
26
29
 
27
- after_create_commit do
28
- IdentityMailer.with(<%= singular_table_name %>: self).email_verify_confirmation.deliver_later
30
+ after_save_commit if: :email_previously_changed? do
31
+ IdentityMailer.with(user: self).email_verify_confirmation.deliver_later
32
+ end
33
+ <% if options.trackable? %>
34
+ after_save_commit if: :email_previously_changed? do
35
+ events.create! action: "email_verification_requested"
36
+ end
37
+
38
+ after_update if: :password_digest_previously_changed? do
39
+ events.create! action: "password_changed"
29
40
  end
30
41
 
31
- after_update_commit if: :email_previously_changed? do
32
- IdentityMailer.with(<%= singular_table_name %>: self).email_verify_confirmation.deliver_later
42
+ after_update if: :verified_previously_changed? do
43
+ events.create! action: "email_verified" if verified?
33
44
  end
45
+ <% end -%>
34
46
  end
@@ -1,7 +1,22 @@
1
1
  class Session < ApplicationRecord
2
2
  belongs_to :<%= singular_table_name %>
3
3
 
4
+ before_create do
5
+ self.user_agent = Current.user_agent
6
+ self.ip_address = Current.ip_address
7
+ self.sudo_at = Time.current
8
+ end
9
+
4
10
  after_create_commit do
5
11
  SessionMailer.with(session: self).signed_in_notification.deliver_later
6
12
  end
13
+ <% if options.trackable? %>
14
+ after_create do
15
+ <%= singular_table_name %>.events.create! action: "signed_in"
16
+ end
17
+
18
+ after_destroy do
19
+ <%= singular_table_name %>.events.create! action: "signed_out"
20
+ end
21
+ <% end -%>
7
22
  end
@@ -39,6 +39,6 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
39
39
  end
40
40
 
41
41
  def sign_in_as(<%= singular_table_name %>)
42
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
42
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
43
43
  end
44
44
  end
@@ -20,6 +20,6 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
20
20
  end
21
21
 
22
22
  def sign_in_as(<%= singular_table_name %>)
23
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
23
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
24
24
  end
25
25
  end
@@ -18,6 +18,6 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
18
18
  end
19
19
 
20
20
  def sign_in_as(<%= singular_table_name %>)
21
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
21
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
22
22
  end
23
23
  end
@@ -19,6 +19,6 @@ class Sessions::SudosControllerTest < 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: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
22
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
23
23
  end
24
24
  end
@@ -16,14 +16,14 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
16
16
  end
17
17
 
18
18
  test "should sign in" do
19
- post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }
19
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "Secret1*3*5*" }
20
20
 
21
21
  assert_enqueued_email_with SessionMailer, :signed_in_notification, args: { session: @<%= singular_table_name %>.sessions.last }
22
22
  assert_response :created
23
23
  end
24
24
 
25
25
  test "should not sign in with wrong credentials" do
26
- post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "SecretWrong1*3" }, headers: { "User-Agent" => "App iOS" }
26
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "SecretWrong1*3" }
27
27
  assert_response :unauthorized
28
28
  end
29
29
 
@@ -33,6 +33,6 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
33
33
  end
34
34
 
35
35
  def sign_in_as(<%= singular_table_name %>)
36
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "App iOS" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
36
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
37
37
  end
38
38
  end
@@ -39,6 +39,6 @@ class Identity::EmailVerificationsControllerTest < ActionDispatch::IntegrationTe
39
39
  end
40
40
 
41
41
  def sign_in_as(<%= singular_table_name %>)
42
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }); <%= singular_table_name %>
42
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); <%= singular_table_name %>
43
43
  end
44
44
  end
@@ -18,18 +18,18 @@ class Identity::EmailsControllerTest < ActionDispatch::IntegrationTest
18
18
  end
19
19
 
20
20
  test "should update email" do
21
- patch identity_email_url, params: { <%= singular_table_name %>: { email: "new_email@hey.com" } }
21
+ patch identity_email_url, params: { email: "new_email@hey.com" }
22
22
  assert_redirected_to root_url
23
23
  end
24
24
 
25
25
  test "should not update email without sudo" do
26
26
  @<%= singular_table_name %>.sessions.last.update! sudo_at: 1.day.ago
27
27
 
28
- patch identity_email_url, params: { <%= singular_table_name %>: { email: "new_email@hey.com" } }
28
+ patch identity_email_url, params: { email: "new_email@hey.com" }
29
29
  assert_redirected_to new_sessions_sudo_url(proceed_to_url: identity_email_url)
30
30
  end
31
31
 
32
32
  def sign_in_as(<%= singular_table_name %>)
33
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }); <%= singular_table_name %>
33
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); <%= singular_table_name %>
34
34
  end
35
35
  end
@@ -49,7 +49,7 @@ class Identity::PasswordResetsControllerTest < ActionDispatch::IntegrationTest
49
49
  end
50
50
 
51
51
  test "should update password" do
52
- patch identity_password_reset_url, params: { token: @sid, <%= singular_table_name %>: { password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" } }
52
+ patch identity_password_reset_url, params: { token: @sid, password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
53
53
  assert_redirected_to sign_in_url
54
54
  end
55
55
 
@@ -11,18 +11,18 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
11
11
  end
12
12
 
13
13
  test "should update password" do
14
- patch password_url, params: { current_password: "Secret1*3*5*", <%= singular_table_name %>: { password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" } }
14
+ patch password_url, params: { current_password: "Secret1*3*5*", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
15
15
  assert_redirected_to root_url
16
16
  end
17
17
 
18
18
  test "should not update password with wrong current password" do
19
- patch password_url, params: { current_password: "SecretWrong1*3", <%= singular_table_name %>: { password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" } }
19
+ patch password_url, params: { current_password: "SecretWrong1*3", password: "Secret6*4*2*", password_confirmation: "Secret6*4*2*" }
20
20
 
21
21
  assert_redirected_to edit_password_url
22
22
  assert_equal "The current password you entered is incorrect", flash[:alert]
23
23
  end
24
24
 
25
25
  def sign_in_as(<%= singular_table_name %>)
26
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }); <%= singular_table_name %>
26
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); <%= singular_table_name %>
27
27
  end
28
28
  end
@@ -8,7 +8,7 @@ class RegistrationsControllerTest < ActionDispatch::IntegrationTest
8
8
 
9
9
  test "should sign up" do
10
10
  assert_difference("<%= class_name %>.count") do
11
- post sign_up_url, params: { <%= singular_table_name %>: { email: "lazaronixon@hey.com", password: "Secret1*3*5*", password_confirmation: "Secret1*3*5*" } }, headers: { "User-Agent" => "Firefox" }
11
+ post sign_up_url, params: { email: "lazaronixon@hey.com", password: "Secret1*3*5*", password_confirmation: "Secret1*3*5*" }
12
12
  end
13
13
 
14
14
  assert_redirected_to root_url
@@ -21,6 +21,6 @@ class Sessions::SudosControllerTest < ActionDispatch::IntegrationTest
21
21
  end
22
22
 
23
23
  def sign_in_as(<%= singular_table_name %>)
24
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
24
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); [<%= singular_table_name %>, response.headers["X-Session-Token"]]
25
25
  end
26
26
  end
@@ -18,7 +18,7 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
18
18
  end
19
19
 
20
20
  test "should sign in" do
21
- post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }
21
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "Secret1*3*5*" }
22
22
  assert_enqueued_email_with SessionMailer, :signed_in_notification, args: { session: @<%= singular_table_name %>.sessions.last }
23
23
 
24
24
  assert_redirected_to root_url
@@ -28,7 +28,7 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
28
28
  end
29
29
 
30
30
  test "should not sign in with wrong credentials" do
31
- post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "SecretWrong1*3" }, headers: { "User-Agent" => "Firefox" }
31
+ post sign_in_url, params: { email: @<%= singular_table_name %>.email, password: "SecretWrong1*3" }
32
32
  assert_redirected_to sign_in_url(email_hint: @<%= singular_table_name %>.email)
33
33
  assert_equal "That email or password is incorrect", flash[:alert]
34
34
 
@@ -47,6 +47,6 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
47
47
  end
48
48
 
49
49
  def sign_in_as(<%= singular_table_name %>)
50
- post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }, headers: { "User-Agent" => "Firefox" }); <%= singular_table_name %>
50
+ post(sign_in_url, params: { email: <%= singular_table_name %>.email, password: "Secret1*3*5*" }); <%= singular_table_name %>
51
51
  end
52
52
  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: 2.8.2
4
+ version: 2.9.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-03-03 00:00:00.000000000 Z
11
+ date: 2022-03-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -34,6 +34,7 @@ files:
34
34
  - lib/generators/authentication/authentication_generator.rb
35
35
  - lib/generators/authentication/templates/config/initializers/omniauth.rb
36
36
  - lib/generators/authentication/templates/config/redis/shared.yml
37
+ - lib/generators/authentication/templates/controllers/api/authentications/events_controller.rb.tt
37
38
  - lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt
38
39
  - lib/generators/authentication/templates/controllers/api/identity/emails_controller.rb.tt
39
40
  - lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt
@@ -41,14 +42,16 @@ files:
41
42
  - lib/generators/authentication/templates/controllers/api/registrations_controller.rb.tt
42
43
  - lib/generators/authentication/templates/controllers/api/sessions/sudos_controller.rb.tt
43
44
  - lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt
45
+ - lib/generators/authentication/templates/controllers/html/authentications/events_controller.rb.tt
44
46
  - lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt
45
47
  - lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt
46
48
  - lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt
47
49
  - lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt
48
50
  - lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt
51
+ - lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt
49
52
  - lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt
50
53
  - lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt
51
- - lib/generators/authentication/templates/controllers/omniauth_controller.rb.tt
54
+ - lib/generators/authentication/templates/erb/authentications/events/index.html.erb
52
55
  - lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt
53
56
  - lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt
54
57
  - lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt
@@ -65,10 +68,11 @@ files:
65
68
  - lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt
66
69
  - lib/generators/authentication/templates/mailers/identity_mailer.rb.tt
67
70
  - lib/generators/authentication/templates/mailers/session_mailer.rb.tt
68
- - lib/generators/authentication/templates/migrations/add_omniauth_migration.rb.tt
71
+ - lib/generators/authentication/templates/migrations/create_events_migration.rb.tt
69
72
  - lib/generators/authentication/templates/migrations/create_sessions_migration.rb.tt
70
73
  - lib/generators/authentication/templates/migrations/create_table_migration.rb.tt
71
74
  - lib/generators/authentication/templates/models/current.rb.tt
75
+ - lib/generators/authentication/templates/models/event.rb.tt
72
76
  - lib/generators/authentication/templates/models/locking.rb.tt
73
77
  - lib/generators/authentication/templates/models/model.rb.tt
74
78
  - lib/generators/authentication/templates/models/session.rb.tt
@@ -1,8 +0,0 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
- def change
3
- add_column :<%= table_name %>, :provider, :string
4
- add_column :<%= table_name %>, :uid, :string
5
- end
6
-
7
- add_index :<%= table_name %>, [:provider, :uid], unique: true
8
- end