authentication-zero 2.8.2 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
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