quo_vadis 2.1.2 → 2.1.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b81cb83f9cd0b6bb6e9af4015dba59b5cef0f5c3fccd5a82ee6d7e1bbc5768a
4
- data.tar.gz: 8a9f5f0c013ec89de6849e9ddb3393fee46b84a2d08b20e606126cf97bba8032
3
+ metadata.gz: d01da21fdfe58d00e4f073036f53df4e0da212a9b202c31bf9fe9ed162e2e2d5
4
+ data.tar.gz: f9b7b777065c7b4e1c83ed54330bc08608cc6020f55f1b72d316de5a1e4e06f5
5
5
  SHA512:
6
- metadata.gz: a7b5e766f22e55e5bc269d00e6fb9132cc54ba2523a72996d0d7da478dbf0662764d29265c591f5847d5f2cfaeaca1e78fb4d48fb8fecb24af0bee9e9c2047e2
7
- data.tar.gz: 47bf8bba82c90f3b7527be6a316ec8f9a4b229077a6846454abecebd6d2ae29910f7e416635d9cc1d54e3b99fe87d4c7d0ca871741907f1987d1ee42bf79994b
6
+ metadata.gz: d3daf72be8a7e1a4545bc8dc7acd77553c62933dd5837e78679a7581cf44356822fbecf4036d5cd8cac5648636a5077e1edd5cb8d6e804ea7c9d55c10b36dc6e
7
+ data.tar.gz: eee0046f0ae978f537f85946946cb4fe0267fd866216108f226411a3df479cb1b7e9c5c334d120a9107298ce9c30f3b8b6736dcaf6248a9c4a5e23a34962bc2e
data/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@
4
4
  ## HEAD
5
5
 
6
6
 
7
+ ## 2.1.5 (27 May 2022)
8
+
9
+ * Order sessions list and display more information.
10
+ * Set status 303 See Other on destroy redirects.
11
+ * Streamline bundler instructions.
12
+
13
+
14
+ ## 2.1.4 (2 October 2021)
15
+
16
+ * Allow metadata for login log.
17
+
18
+
19
+ ## 2.1.3 (30 September 2021)
20
+
21
+ * Pass IP and timestamp as paramenters to mailer.
22
+
23
+
24
+ ## 2.1.2 (30 September 2021)
25
+
26
+ * Delete existing recovery codes when generating new ones.
27
+
28
+
7
29
  ## 2.1.1 (8 July 2021)
8
30
 
9
31
  * Remove unnecessary route names.
data/README.md CHANGED
@@ -37,11 +37,9 @@ Simple to integrate into your application. The main task is customising the exa
37
37
  Add the gem to your Gemfile:
38
38
 
39
39
  ```ruby
40
- gem 'quo_vadis', '~> 2.0'
40
+ bundle add 'quo_vadis'
41
41
  ```
42
42
 
43
- Then run `bundle install`.
44
-
45
43
  Next, add the database tables:
46
44
 
47
45
  ```
@@ -119,7 +117,7 @@ end
119
117
 
120
118
  __`login(model, browser_session = true)`__
121
119
 
122
- To log in a user who has authenticated with a password, call `#login(model, browser_session = true)`. For the `browser_session` argument, pass `true` to log in for the duration of the browser session, or `false` to log in for `QuoVadis.session_lifetime` (which could be the browser session anyway).
120
+ To log in a user who has authenticated with a password, call `#login(model, browser_session = true, metadata: {})`. For the `browser_session` argument, optionally pass `true` to log in for the duration of the browser session, or `false` to log in for `QuoVadis.session_lifetime` (which could be the browser session anyway). Any metadata are stored in the log entry for the login.
123
121
 
124
122
  __`request_confirmation(model)`__
125
123
 
@@ -17,7 +17,7 @@ module QuoVadis
17
17
 
18
18
  if account
19
19
  token = QuoVadis::PasswordResetToken.generate account
20
- QuoVadis.deliver :reset_password, email: account.model.email, url: quo_vadis.password_reset_url(token)
20
+ QuoVadis.deliver :reset_password, {email: account.model.email, url: quo_vadis.password_reset_url(token)}
21
21
  end
22
22
 
23
23
  redirect_to password_resets_path, notice: QuoVadis.translate('flash.password_reset.create')
@@ -9,7 +9,7 @@ module QuoVadis
9
9
 
10
10
  def index
11
11
  @qv_session = qv.session
12
- @qv_sessions = @qv_session.account.sessions
12
+ @qv_sessions = @qv_session.account.sessions.new_to_old
13
13
  end
14
14
 
15
15
 
@@ -58,12 +58,12 @@ module QuoVadis
58
58
  current_qv_session.account.sessions.destroy params[:id]
59
59
  qv.log current_qv_session.account, Log::LOGOUT_OTHER
60
60
  flash[:notice] = QuoVadis.translate 'flash.logout.other'
61
- redirect_to action: :index
61
+ redirect_to action: :index, status: :see_other
62
62
  else # this session
63
63
  qv.log authenticated_model.qv_account, Log::LOGOUT
64
64
  qv.logout
65
65
  flash[:notice] = QuoVadis.translate 'flash.logout.self'
66
- redirect_to main_app.root_path
66
+ redirect_to main_app.root_path, status: :see_other
67
67
  end
68
68
  end
69
69
 
@@ -14,7 +14,7 @@ module QuoVadis
14
14
  account.sessions.each &:reset_authenticated_with_second_factor # OWASP ASV v4.0, 2.8.6
15
15
  qv.log account, Log::TWOFA_DEACTIVATED
16
16
  QuoVadis.notify :twofa_deactivated_notification, email: authenticated_model.email
17
- redirect_to twofa_path, notice: QuoVadis.translate('flash.2fa.invalidated')
17
+ redirect_to twofa_path, notice: QuoVadis.translate('flash.2fa.invalidated'), status: :see_other
18
18
  end
19
19
 
20
20
  private
@@ -14,52 +14,52 @@ module QuoVadis
14
14
  end
15
15
 
16
16
  def email_change_notification
17
- @timestamp = Time.now
18
- @ip = QuoVadis::CurrentRequestDetails.ip
17
+ @timestamp = params[:timestamp]
18
+ @ip = params[:ip]
19
19
  _mail params[:email], QuoVadis.translate('mailer.notification.email_change')
20
20
  end
21
21
 
22
22
  def identifier_change_notification
23
- @timestamp = Time.now
23
+ @timestamp = params[:timestamp]
24
24
  @identifier = params[:identifier]
25
- @ip = QuoVadis::CurrentRequestDetails.ip
25
+ @ip = params[:ip]
26
26
  _mail params[:email], QuoVadis.translate('mailer.notification.identifier_change',
27
27
  identifier: params[:identifier])
28
28
  end
29
29
 
30
30
  def password_change_notification
31
- @timestamp = Time.now
32
- @ip = QuoVadis::CurrentRequestDetails.ip
31
+ @timestamp = params[:timestamp]
32
+ @ip = params[:ip]
33
33
  _mail params[:email], QuoVadis.translate('mailer.notification.password_change')
34
34
  end
35
35
 
36
36
  def password_reset_notification
37
- @timestamp = Time.now
38
- @ip = QuoVadis::CurrentRequestDetails.ip
37
+ @timestamp = params[:timestamp]
38
+ @ip = params[:ip]
39
39
  _mail params[:email], QuoVadis.translate('mailer.notification.password_reset')
40
40
  end
41
41
 
42
42
  def totp_setup_notification
43
- @timestamp = Time.now
44
- @ip = QuoVadis::CurrentRequestDetails.ip
43
+ @timestamp = params[:timestamp]
44
+ @ip = params[:ip]
45
45
  _mail params[:email], QuoVadis.translate('mailer.notification.totp_setup')
46
46
  end
47
47
 
48
48
  def totp_reuse_notification
49
- @timestamp = Time.now
50
- @ip = QuoVadis::CurrentRequestDetails.ip
49
+ @timestamp = params[:timestamp]
50
+ @ip = params[:ip]
51
51
  _mail params[:email], QuoVadis.translate('mailer.notification.totp_reuse')
52
52
  end
53
53
 
54
54
  def twofa_deactivated_notification
55
- @timestamp = Time.now
56
- @ip = QuoVadis::CurrentRequestDetails.ip
55
+ @timestamp = params[:timestamp]
56
+ @ip = params[:ip]
57
57
  _mail params[:email], QuoVadis.translate('mailer.notification.twofa_deactivated')
58
58
  end
59
59
 
60
60
  def recovery_codes_generation_notification
61
- @timestamp = Time.now
62
- @ip = QuoVadis::CurrentRequestDetails.ip
61
+ @timestamp = params[:timestamp]
62
+ @ip = params[:ip]
63
63
  _mail params[:email], QuoVadis.translate('mailer.notification.recovery_codes_generation')
64
64
  end
65
65
 
@@ -9,6 +9,7 @@ module QuoVadis
9
9
 
10
10
  belongs_to :account
11
11
  validates :ip, presence: true
12
+ scope :new_to_old, -> { order create_at: :desc }
12
13
 
13
14
  attribute :last_seen_at, :datetime, default: -> { Time.now.utc }
14
15
 
@@ -3,6 +3,9 @@
3
3
  <table>
4
4
  <thead>
5
5
  <tr>
6
+ <th>Signed in</th>
7
+ <th>Last seen</th>
8
+ <th>2FA used</th>
6
9
  <th>IP</th>
7
10
  <th>User agent</th>
8
11
  <th></th>
@@ -11,6 +14,9 @@
11
14
  <tbody>
12
15
  <% @qv_sessions.each do |sess| %>
13
16
  <tr>
17
+ <td><time datetime="<%= sess.created_at.to_formatted_s(:iso_8601) %>"><%= sess.created_at.to_formatted_s('%-d %B %Y') %></time></td>
18
+ <td><time datetime="<%= sess.last_seen_at.to_formatted_s(:iso_8601) %>"><%= sess.last_seen_at.to_formatted_s('%-d %B %Y') %></time></td>
19
+ <td><%= sess.second_factor_authenticated? ? 'Yes' : 'No' %></td>
14
20
  <td><%= sess.ip %></td>
15
21
  <td><%= sess.user_agent %></td>
16
22
  <td>
@@ -36,8 +36,8 @@ module QuoVadis
36
36
  #
37
37
  # browser_session - true: login only for duration of browser session
38
38
  # false: login for QuoVadis.session_lifetime (which may be browser session anyway)
39
- def login(model, browser_session = true)
40
- qv.log model.qv_account, Log::LOGIN_SUCCESS
39
+ def login(model, browser_session = true, metadata: {})
40
+ qv.log model.qv_account, Log::LOGIN_SUCCESS, metadata
41
41
 
42
42
  qv.prevent_rails_session_fixation
43
43
 
@@ -87,7 +87,7 @@ module QuoVadis
87
87
 
88
88
  def request_confirmation(model)
89
89
  token = QuoVadis::AccountConfirmationToken.generate model.qv_account
90
- QuoVadis.deliver :account_confirmation, email: model.email, url: quo_vadis.confirmation_url(token)
90
+ QuoVadis.deliver :account_confirmation, {email: model.email, url: quo_vadis.confirmation_url(token)}
91
91
  session[:account_pending_confirmation] = model.qv_account.id
92
92
 
93
93
  flash[:notice] = QuoVadis.translate 'flash.confirmation.create'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QuoVadis
4
- VERSION = '2.1.2'
4
+ VERSION = '2.1.5'
5
5
  end
data/lib/quo_vadis.rb CHANGED
@@ -73,12 +73,14 @@ module QuoVadis
73
73
  end
74
74
 
75
75
  def notify(action, params)
76
- QuoVadis::Mailer.with(params).send(action).deliver_later
76
+ deliver(action, params, later: true)
77
77
  end
78
78
 
79
- def deliver(action, params)
80
- mail = QuoVadis::Mailer.with(params).send(action)
81
- QuoVadis.enqueue_transactional_emails ?
79
+ def deliver(action, params, later: QuoVadis.enqueue_transactional_emails)
80
+ mail = QuoVadis::Mailer
81
+ .with(params.merge(ip: QuoVadis::CurrentRequestDetails.ip, timestamp: Time.now))
82
+ .send(action)
83
+ later ?
82
84
  mail.deliver_later :
83
85
  mail.deliver_now
84
86
  end
data/quo_vadis.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Andy Stewart']
9
9
  spec.email = ['boss@airbladesoftware.com']
10
10
 
11
- spec.summary = 'Multifactor authentication for Rails 6.'
11
+ spec.summary = 'Multifactor authentication for Rails 6 and 7.'
12
12
  spec.homepage = 'https://github.com/airblade/quo_vadis'
13
13
  spec.license = 'MIT'
14
14
 
@@ -44,14 +44,16 @@ class MailerTest < ActionMailer::TestCase
44
44
 
45
45
 
46
46
  test 'email change notification' do
47
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').email_change_notification
47
+ email = QuoVadis::Mailer.with(
48
+ email: 'Foo <foo@example.com>',
49
+ ip: '1.2.3.4',
50
+ timestamp: Time.now
51
+ ).email_change_notification
48
52
 
49
53
  # freeze_time
50
54
 
51
55
  assert_emails 1 do
52
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
53
- email.deliver_now
54
- end
56
+ email.deliver_now
55
57
  end
56
58
 
57
59
  assert_equal ['foo@example.com'], email.to
@@ -62,14 +64,17 @@ class MailerTest < ActionMailer::TestCase
62
64
 
63
65
 
64
66
  test 'identifier change notification' do
65
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>', identifier: 'email').identifier_change_notification
67
+ email = QuoVadis::Mailer.with(
68
+ email: 'Foo <foo@example.com>',
69
+ identifier: 'email',
70
+ ip: '1.2.3.4',
71
+ timestamp: Time.now
72
+ ).identifier_change_notification
66
73
 
67
74
  # freeze_time
68
75
 
69
76
  assert_emails 1 do
70
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
71
- email.deliver_now
72
- end
77
+ email.deliver_now
73
78
  end
74
79
 
75
80
  assert_equal ['foo@example.com'], email.to
@@ -80,14 +85,16 @@ class MailerTest < ActionMailer::TestCase
80
85
 
81
86
 
82
87
  test 'password change notification' do
83
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').password_change_notification
88
+ email = QuoVadis::Mailer.with(
89
+ email: 'Foo <foo@example.com>',
90
+ ip: '1.2.3.4',
91
+ timestamp: Time.now
92
+ ).password_change_notification
84
93
 
85
94
  # freeze_time
86
95
 
87
96
  assert_emails 1 do
88
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
89
- email.deliver_now
90
- end
97
+ email.deliver_now
91
98
  end
92
99
 
93
100
  assert_equal ['foo@example.com'], email.to
@@ -98,14 +105,16 @@ class MailerTest < ActionMailer::TestCase
98
105
 
99
106
 
100
107
  test 'password reset notification' do
101
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').password_reset_notification
108
+ email = QuoVadis::Mailer.with(
109
+ email: 'Foo <foo@example.com>',
110
+ ip: '1.2.3.4',
111
+ timestamp: Time.now
112
+ ).password_reset_notification
102
113
 
103
114
  # freeze_time
104
115
 
105
116
  assert_emails 1 do
106
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
107
- email.deliver_now
108
- end
117
+ email.deliver_now
109
118
  end
110
119
 
111
120
  assert_equal ['foo@example.com'], email.to
@@ -116,14 +125,16 @@ class MailerTest < ActionMailer::TestCase
116
125
 
117
126
 
118
127
  test 'totp setup notification' do
119
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').totp_setup_notification
128
+ email = QuoVadis::Mailer.with(
129
+ email: 'Foo <foo@example.com>',
130
+ ip: '1.2.3.4',
131
+ timestamp: Time.now
132
+ ).totp_setup_notification
120
133
 
121
134
  # freeze_time
122
135
 
123
136
  assert_emails 1 do
124
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
125
- email.deliver_now
126
- end
137
+ email.deliver_now
127
138
  end
128
139
 
129
140
  assert_equal ['foo@example.com'], email.to
@@ -134,14 +145,16 @@ class MailerTest < ActionMailer::TestCase
134
145
 
135
146
 
136
147
  test 'totp reuse notification' do
137
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').totp_reuse_notification
148
+ email = QuoVadis::Mailer.with(
149
+ email: 'Foo <foo@example.com>',
150
+ ip: '1.2.3.4',
151
+ timestamp: Time.now
152
+ ).totp_reuse_notification
138
153
 
139
154
  # freeze_time
140
155
 
141
156
  assert_emails 1 do
142
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
143
- email.deliver_now
144
- end
157
+ email.deliver_now
145
158
  end
146
159
 
147
160
  assert_equal ['foo@example.com'], email.to
@@ -152,14 +165,16 @@ class MailerTest < ActionMailer::TestCase
152
165
 
153
166
 
154
167
  test '2fa deactivated notification' do
155
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').twofa_deactivated_notification
168
+ email = QuoVadis::Mailer.with(
169
+ email: 'Foo <foo@example.com>',
170
+ ip: '1.2.3.4',
171
+ timestamp: Time.now
172
+ ).twofa_deactivated_notification
156
173
 
157
174
  # freeze_time
158
175
 
159
176
  assert_emails 1 do
160
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
161
- email.deliver_now
162
- end
177
+ email.deliver_now
163
178
  end
164
179
 
165
180
  assert_equal ['foo@example.com'], email.to
@@ -170,14 +185,16 @@ class MailerTest < ActionMailer::TestCase
170
185
 
171
186
 
172
187
  test 'recovery codes generation notification' do
173
- email = QuoVadis::Mailer.with(email: 'Foo <foo@example.com>').recovery_codes_generation_notification
188
+ email = QuoVadis::Mailer.with(
189
+ email: 'Foo <foo@example.com>',
190
+ ip: '1.2.3.4',
191
+ timestamp: Time.now
192
+ ).recovery_codes_generation_notification
174
193
 
175
194
  # freeze_time
176
195
 
177
196
  assert_emails 1 do
178
- QuoVadis::CurrentRequestDetails.set(ip: '1.2.3.4') do
179
- email.deliver_now
180
- end
197
+ email.deliver_now
181
198
  end
182
199
 
183
200
  assert_equal ['foo@example.com'], email.to
@@ -13,8 +13,11 @@ class AccountTest < ActiveSupport::TestCase
13
13
 
14
14
 
15
15
  test 'notifies on identifier change when notifier is not email' do
16
+ freeze_time
16
17
  p = Person.create! username: 'bob', email: 'bob@example.com', password: 'secretsecret'
17
- assert_enqueued_email_with QuoVadis::Mailer, :identifier_change_notification, args: {email: 'bob@example.com', identifier: 'username'} do
18
+ assert_enqueued_email_with QuoVadis::Mailer,
19
+ :identifier_change_notification,
20
+ args: {email: 'bob@example.com', identifier: 'username', ip: nil, timestamp: Time.now} do
18
21
  assert_enqueued_emails 1 do
19
22
  p.update username: 'robert@example.com'
20
23
  end
@@ -23,8 +26,11 @@ class AccountTest < ActiveSupport::TestCase
23
26
 
24
27
 
25
28
  test 'does not notify on identifier change when notifier is email' do
29
+ freeze_time
26
30
  u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
27
- assert_enqueued_email_with QuoVadis::Mailer, :email_change_notification, args: {email: 'bob@example.com'} do
31
+ assert_enqueued_email_with QuoVadis::Mailer,
32
+ :email_change_notification,
33
+ args: {email: 'bob@example.com', ip: nil, timestamp: Time.now} do
28
34
  assert_enqueued_emails 1 do
29
35
  u.update email: 'robert@example.com'
30
36
  end
@@ -58,8 +58,11 @@ class ModelTest < ActiveSupport::TestCase
58
58
 
59
59
 
60
60
  test 'notifies on email change' do
61
+ freeze_time
61
62
  u = User.create! name: 'bob', email: 'bob@example.com', password: '123456789abc'
62
- assert_enqueued_email_with QuoVadis::Mailer, :email_change_notification, args: {email: 'bob@example.com'} do
63
+ assert_enqueued_email_with QuoVadis::Mailer,
64
+ :email_change_notification,
65
+ args: {email: 'bob@example.com', ip: nil, timestamp: Time.now} do
63
66
  u.update email: 'robert@example.com'
64
67
  end
65
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quo_vadis
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Stewart
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-30 00:00:00.000000000 Z
11
+ date: 2022-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -224,8 +224,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
224
  - !ruby/object:Gem::Version
225
225
  version: '0'
226
226
  requirements: []
227
- rubygems_version: 3.1.4
227
+ rubygems_version: 3.2.22
228
228
  signing_key:
229
229
  specification_version: 4
230
- summary: Multifactor authentication for Rails 6.
230
+ summary: Multifactor authentication for Rails 6 and 7.
231
231
  test_files: []