devise-otp 0.7.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +18 -8
  3. data/.gitignore +2 -0
  4. data/Appraisals +36 -0
  5. data/CHANGELOG.md +4 -1
  6. data/Gemfile +12 -0
  7. data/README.md +8 -7
  8. data/app/assets/stylesheets/devise-otp.css +4 -0
  9. data/app/controllers/devise_otp/devise/otp_credentials_controller.rb +4 -6
  10. data/app/controllers/devise_otp/devise/otp_tokens_controller.rb +7 -8
  11. data/app/views/devise/otp_tokens/show.html.erb +1 -1
  12. data/config/locales/en.yml +0 -2
  13. data/devise-otp.gemspec +8 -16
  14. data/gemfiles/rails_7.0.gemfile +25 -0
  15. data/gemfiles/rails_7.1.gemfile +21 -0
  16. data/gemfiles/rails_7.2.gemfile +17 -0
  17. data/gemfiles/rails_8.0.gemfile +17 -0
  18. data/lib/devise-otp/version.rb +1 -1
  19. data/lib/devise_otp_authenticatable/controllers/helpers.rb +5 -28
  20. data/lib/generators/active_record/templates/migration.rb +1 -1
  21. data/test/dummy/app/assets/javascripts/application.js +0 -1
  22. data/test/dummy/app/assets/stylesheets/application.css +1 -0
  23. data/test/dummy/app/views/layouts/application.html.erb +7 -1
  24. data/test/dummy/config/routes.rb +1 -1
  25. data/test/dummy/db/migrate/20240604000001_create_admins.rb +1 -1
  26. data/test/integration/disable_token_test.rb +3 -0
  27. data/test/integration/enable_otp_form_test.rb +17 -0
  28. data/test/integration/persistence_test.rb +3 -0
  29. data/test/integration/refresh_test.rb +9 -0
  30. data/test/integration/reset_token_test.rb +3 -0
  31. data/test/integration/sign_in_test.rb +30 -0
  32. data/test/orm/active_record.rb +6 -1
  33. metadata +19 -118
  34. data/app/assets/javascripts/devise-otp.js +0 -1
  35. data/app/assets/javascripts/qrcode.js +0 -609
  36. data/docs/QR_CODES.md +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 591466bedc565bb6914c791657c39f3337ab5cb8c91bad78027ce2a27e7008ae
4
- data.tar.gz: b7b7edc112fd429cf51ad1c48adf126138b3f875cdb103c6259cd316237ae5d1
3
+ metadata.gz: 7a2884c76d255b2c2bb3b40859db7018c5668d49fcb6897141dacd8d7df0bc62
4
+ data.tar.gz: 3c7ee30dd96a9711b4b4194cb2b94cea6abb06113dda2ef58b70c9a96c998ec4
5
5
  SHA512:
6
- metadata.gz: 299c6b4523d6f180fa3c795b1fc56a00eceeafdff0f36e9086f26da9c958acbcbabd2329919105fa24cf433bc14eeeba44642a0dff75189473811dd48da3088f
7
- data.tar.gz: 6caad7adc9cd91b05f9e05cb0d0364e9aca50d7d9cc67b97c58aeb7d465f365bf42e4fad1f37f54d19d48452b844e9ede4156f8f25898e463a99951e5c66c8df
6
+ metadata.gz: b099c20c5c6d76fc2e1226511615bb43f2b081620f01bbf1bcc939cec66e286aa3536f8a654495907607e42d23e7f3efd9bb3377ed3a1a8a6ef522ec5e9568e1
7
+ data.tar.gz: 731d1dc34877d0fe91bb092b33ce4ee7c302c4cb75183daa3ff67a0df7f6d242bc86b3ab4e0923683b8408c8f1e6bab8e8a1d1c5fa10b9b0e104617a9b87ded7
@@ -7,28 +7,38 @@ on:
7
7
 
8
8
  jobs:
9
9
  rspec:
10
- runs-on: ubuntu-20.04
10
+ runs-on: ubuntu-latest
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  ruby:
15
+ - '3.3'
16
+ - '3.2'
15
17
  - '3.1'
18
+ - 'head'
19
+ rails:
20
+ - rails_8.0
21
+ - rails_7.2
22
+ - rails_7.1
23
+ - rails_7.0
24
+ exclude:
25
+ - ruby: '3.1'
26
+ rails: 'rails_8.0'
27
+
28
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
29
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.rails }}.gemfile
16
30
 
17
31
  steps:
18
32
  - name: Checkout
19
- uses: actions/checkout@v2
33
+ uses: actions/checkout@v4
20
34
 
21
35
  - name: Setup Ruby
22
36
  uses: ruby/setup-ruby@v1
23
37
  with:
24
38
  ruby-version: ${{ matrix.ruby }}
25
-
26
- - name: Bundle
27
- run: |
28
- gem install bundler
29
- bundle install --jobs 4 --retry 3
39
+ bundler-cache: true
30
40
 
31
41
  - name: Run tests
32
42
  env:
33
43
  DEVISE_ORM: active_record
34
- run: rake test
44
+ run: bundle exec rake test
data/.gitignore CHANGED
@@ -38,7 +38,9 @@ test/dummy/db/*.sqlite3
38
38
  test/dummy/db/*.sqlite3-shm
39
39
  test/dummy/db/*.sqlite3-wal
40
40
 
41
+ # Ignore Gemfile.lock
41
42
  Gemfile.lock
43
+ gemfiles/*.lock
42
44
 
43
45
  # Generated test files
44
46
  tmp/*
data/Appraisals ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise 'rails_7.0' do
4
+ gem 'rails', '~> 7.0.0'
5
+ gem 'sqlite3', '~> 1.5.0'
6
+
7
+ # Fix: LoadError: cannot load such file -- base64
8
+ install_if '-> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.3.0") }' do
9
+ gem 'base64'
10
+ gem 'bigdecimal'
11
+ gem 'mutex_m'
12
+ gem 'drb'
13
+ gem 'logger'
14
+ end
15
+ end
16
+
17
+ appraise 'rails_7.1' do
18
+ gem 'rails', '~> 7.1.0'
19
+ gem 'sqlite3', '~> 1.5.0'
20
+
21
+ # Fix:
22
+ # warning: logger was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.5.0.
23
+ # Add logger to your Gemfile or gemspec.
24
+ install_if '-> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0") }' do
25
+ gem 'logger'
26
+ end
27
+ end
28
+
29
+ appraise 'rails_7.2' do
30
+ gem 'rails', '~> 7.2.0'
31
+ gem 'sqlite3', '~> 1.5.0'
32
+ end
33
+
34
+ appraise 'rails_8.0' do
35
+ gem 'rails', '~> 8.0.0'
36
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - Upgrade gemspec to support Rails v7.2
6
+
3
7
  ## 0.7.0
4
8
 
5
9
  Breaking changes:
@@ -57,4 +61,3 @@ Fixes:
57
61
 
58
62
  - mandatory otp fix by @cotcomsol in #68
59
63
  - remove success message by @strzibny in #69
60
-
data/Gemfile CHANGED
@@ -2,3 +2,15 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in devise-otp.gemspec
4
4
  gemspec
5
+
6
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
7
+
8
+ gem "capybara"
9
+ gem "minitest-reporters", ">= 0.5.0"
10
+ gem "puma"
11
+ gem "rake"
12
+ gem "rdoc"
13
+ gem "shoulda"
14
+ gem "sprockets-rails"
15
+ gem "sqlite3", "~> 2.1"
16
+ gem "standardrb"
data/README.md CHANGED
@@ -13,7 +13,7 @@ Some of the compatible token devices are:
13
13
  * [Google Authenticator](https://code.google.com/p/google-authenticator/)
14
14
  * [FreeOTP](https://fedorahosted.org/freeotp/)
15
15
 
16
- Device OTP was recently updated to work with Rails 7 and Turbo.
16
+ Device OTP was recently updated to work with Rails 7+ and Turbo.
17
17
 
18
18
  ## Sponsor
19
19
 
@@ -58,10 +58,13 @@ Don't forget to migrate:
58
58
 
59
59
  rake db:migrate
60
60
 
61
- Add the gem's JavaScript to you `application.js`:
61
+ ### Default CSS
62
62
 
63
- //= require devise-otp
63
+ To use the default CSS for devise-otp, just require the devise-otp.css file as usual in your application.css file (or equivalent):
64
64
 
65
+ *= require devise-otp
66
+
67
+ It might be even easier to just copy the styles to your project.
65
68
 
66
69
  ### Custom views
67
70
 
@@ -77,9 +80,7 @@ The install generator also installs an english copy of a Devise OTP i18n file. T
77
80
 
78
81
  ### QR codes
79
82
 
80
- By default, Devise OTP assumes that you use [Sprockets](https://github.com/rails/sprockets) to render assets and so will use the ([qrcode.js](/app/assets/javascripts/qrcode.js)) embeded library to render the QR code.
81
-
82
- If you need something more, have a look at [QR codes](/docs/QR_CODES.md) documentation file.
83
+ Devise OTP generates QR Codes directly as SVG's via the [rqrcode](https://github.com/whomwah/rqrcode), so there are no JavaScript (or Sprockets) dependencies.
83
84
 
84
85
  ## Configuration
85
86
 
@@ -102,7 +103,7 @@ Enforcing mandatory OTP requires adding the ensure\_mandatory\_{scope}\_otp! met
102
103
 
103
104
  ## Authors
104
105
 
105
- The project was originally started by Lele Forzani by forking [devise_google_authenticator](https://github.com/AsteriskLabs/devise_google_authenticator) and still contains some devise_google_authenticator code. It's now maintained by [Josef Strzibny](https://github.com/strzibny/).
106
+ The project was originally started by Lele Forzani by forking [devise_google_authenticator](https://github.com/AsteriskLabs/devise_google_authenticator) and still contains some devise_google_authenticator code. It's now maintained by [Josef Strzibny](https://github.com/strzibny/) and [Laney Stroup](https://github.com/strouptl).
106
107
 
107
108
  Contributions are welcome!
108
109
 
@@ -0,0 +1,4 @@
1
+ .qrcode-container {
2
+ max-width: 300px;
3
+ margin: 0 auto;
4
+ }
@@ -26,17 +26,15 @@ module DeviseOtp
26
26
  # signs the resource in, if the OTP token is valid and the user has a valid challenge
27
27
  #
28
28
  def update
29
- if @token.blank?
30
- otp_set_flash_message(:alert, :token_blank)
31
- redirect_to otp_credential_path_for(resource_name, challenge: @challenge, recovery: @recovery)
32
- elsif resource.otp_challenge_valid? && resource.validate_otp_token(@token, @recovery)
29
+ if resource.otp_challenge_valid? && resource.validate_otp_token(@token, @recovery)
33
30
  sign_in(resource_name, resource)
34
31
 
35
32
  otp_set_trusted_device_for(resource) if params[:enable_persistence] == "true"
36
33
  otp_refresh_credentials_for(resource)
37
34
  respond_with resource, location: after_sign_in_path_for(resource)
38
35
  else
39
- otp_set_flash_message :alert, :token_invalid
36
+ kind = (@token.blank? ? :token_blank : :token_invalid)
37
+ otp_set_flash_message :alert, kind, :now => true
40
38
  render :show
41
39
  end
42
40
  end
@@ -103,7 +101,7 @@ module DeviseOtp
103
101
  end
104
102
 
105
103
  def failed_refresh
106
- otp_set_flash_message :alert, :invalid_refresh
104
+ otp_set_flash_message :alert, :invalid_refresh, :now => true
107
105
  render :refresh
108
106
  end
109
107
 
@@ -33,9 +33,9 @@ module DeviseOtp
33
33
  if resource.valid_otp_token?(params[:confirmation_code])
34
34
  resource.enable_otp!
35
35
  otp_set_flash_message :success, :successfully_updated
36
- redirect_to action: :show
36
+ redirect_to otp_token_path_for(resource)
37
37
  else
38
- otp_set_flash_message :danger, :could_not_confirm
38
+ otp_set_flash_message :danger, :could_not_confirm, :now => true
39
39
  render :edit
40
40
  end
41
41
  end
@@ -48,7 +48,7 @@ module DeviseOtp
48
48
  otp_set_flash_message :success, :successfully_disabled_otp
49
49
  end
50
50
 
51
- redirect_to action: :show
51
+ redirect_to otp_token_path_for(resource)
52
52
  end
53
53
 
54
54
  #
@@ -59,7 +59,7 @@ module DeviseOtp
59
59
  otp_set_flash_message :success, :successfully_set_persistence
60
60
  end
61
61
 
62
- redirect_to action: :show
62
+ redirect_to otp_token_path_for(resource)
63
63
  end
64
64
 
65
65
  #
@@ -70,7 +70,7 @@ module DeviseOtp
70
70
  otp_set_flash_message :success, :successfully_cleared_persistence
71
71
  end
72
72
 
73
- redirect_to action: :show
73
+ redirect_to otp_token_path_for(resource)
74
74
  end
75
75
 
76
76
  #
@@ -81,7 +81,7 @@ module DeviseOtp
81
81
  otp_set_flash_message :notice, :successfully_reset_persistence
82
82
  end
83
83
 
84
- redirect_to action: :show
84
+ redirect_to otp_token_path_for(resource)
85
85
  end
86
86
 
87
87
  def recovery
@@ -100,7 +100,7 @@ module DeviseOtp
100
100
  otp_set_flash_message :success, :successfully_reset_otp
101
101
  end
102
102
 
103
- redirect_to action: :edit
103
+ redirect_to edit_otp_token_path_for(resource)
104
104
  end
105
105
 
106
106
  private
@@ -109,7 +109,6 @@ module DeviseOtp
109
109
  ensure_resource!
110
110
 
111
111
  if needs_credentials_refresh?(resource)
112
- otp_set_flash_message :notice, :need_to_refresh_credentials
113
112
  redirect_to refresh_otp_credential_path_for(resource)
114
113
  end
115
114
  end
@@ -7,7 +7,7 @@
7
7
  <%= render :partial => 'trusted_devices' if trusted_devices_enabled? %>
8
8
 
9
9
  <% unless otp_mandatory_on?(resource) %>
10
- <%= button_to I18n.t('disable_link', :scope => 'devise.otp.otp_tokens'), @resource, :method => :delete, :data => { "turbo-method": "DELETE" } %>
10
+ <%= button_to I18n.t('disable_link', :scope => 'devise.otp.otp_tokens'), otp_token_path_for(resource), :method => :delete, :data => { "turbo-method": "DELETE" } %>
11
11
  <% end %>
12
12
  <% else %>
13
13
  <%= link_to I18n.t('enable_link', :scope => 'devise.otp.otp_tokens'), edit_otp_token_path_for(resource) %>
@@ -14,7 +14,6 @@ en:
14
14
  otp_session_invalid: Session invalid. Please start again.
15
15
  token_invalid: 'The token you provided was invalid.'
16
16
  token_blank: 'You need to type in the token you generated with your device.'
17
- need_to_refresh_credentials: 'We need to check your credentials before you can change these settings.'
18
17
  valid_refresh: 'Thank you, your credentials were accepted.'
19
18
  invalid_refresh: 'Sorry, you provided the wrong credentials.'
20
19
  credentials_refresh:
@@ -41,7 +40,6 @@ en:
41
40
  successfully_set_persistence: 'Your device is now trusted.'
42
41
  successfully_cleared_persistence: 'Your device has been removed from the list of trusted devices.'
43
42
  successfully_reset_persistence: 'Your list of trusted devices has been cleared.'
44
- need_to_refresh_credentials: 'We need to check your credentials before you can change these settings.'
45
43
  recovery:
46
44
  title: 'Your Emergency Recovery Codes'
47
45
  explain: 'Take note or print these recovery codes. The will allow you to log back in in case your token device is lost, stolen, or unavailable.'
data/devise-otp.gemspec CHANGED
@@ -5,25 +5,17 @@ require_relative "lib/devise-otp/version"
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "devise-otp"
7
7
  gem.version = Devise::OTP::VERSION
8
- gem.authors = ["Lele Forzani", "Josef Strzibny"]
9
- gem.email = ["lele@windmill.it", "strzibny@strzibny.name"]
10
- gem.description = "Time Based OTP/rfc6238 compatible authentication for Devise"
8
+ gem.authors = ["Lele Forzani", "Josef Strzibny", "Laney Stroup"]
9
+ gem.email = ["lele@windmill.it", "strzibny@strzibny.name", "laney@stroupsolutions.com"]
10
+ gem.description = "OTP authentication for Devise"
11
11
  gem.summary = "Time Based OTP/rfc6238 compatible authentication for Devise"
12
- gem.homepage = "http://git.windmill.it/wm/devise-otp"
12
+ gem.homepage = "https://github.com/wmlele/devise-otp"
13
13
 
14
14
  gem.files = `git ls-files`.split($/)
15
15
  gem.require_paths = ["lib"]
16
16
 
17
- gem.add_runtime_dependency "rails", ">= 6.1", "< 7.2"
18
- gem.add_runtime_dependency "devise", ">= 4.8.0", "< 5.0"
19
- gem.add_runtime_dependency "rotp", ">= 2.0.0"
20
-
21
- gem.add_development_dependency "capybara"
22
- gem.add_development_dependency "minitest-reporters", ">= 0.5.0"
23
- gem.add_development_dependency "puma"
24
- gem.add_development_dependency "rdoc"
25
- gem.add_development_dependency "shoulda"
26
- gem.add_development_dependency "sprockets-rails"
27
- gem.add_development_dependency "sqlite3", "~> 1.4"
28
- gem.add_development_dependency "standardrb"
17
+ gem.add_dependency "rails", ">= 7.0"
18
+ gem.add_dependency "devise", ">= 4.8.0", "< 5.0"
19
+ gem.add_dependency "rotp", ">= 2.0.0"
20
+ gem.add_dependency "rqrcode", "~> 2.0"
29
21
  end
@@ -0,0 +1,25 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
6
+ gem "capybara"
7
+ gem "minitest-reporters", ">= 0.5.0"
8
+ gem "puma"
9
+ gem "rake"
10
+ gem "rdoc"
11
+ gem "shoulda"
12
+ gem "sprockets-rails"
13
+ gem "sqlite3", "~> 1.5.0"
14
+ gem "standardrb"
15
+ gem "rails", "~> 7.0.0"
16
+
17
+ install_if -> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.3.0") } do
18
+ gem "base64"
19
+ gem "bigdecimal"
20
+ gem "mutex_m"
21
+ gem "drb"
22
+ gem "logger"
23
+ end
24
+
25
+ gemspec path: "../"
@@ -0,0 +1,21 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
6
+ gem "capybara"
7
+ gem "minitest-reporters", ">= 0.5.0"
8
+ gem "puma"
9
+ gem "rake"
10
+ gem "rdoc"
11
+ gem "shoulda"
12
+ gem "sprockets-rails"
13
+ gem "sqlite3", "~> 1.5.0"
14
+ gem "standardrb"
15
+ gem "rails", "~> 7.1.0"
16
+
17
+ install_if -> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0") } do
18
+ gem "logger"
19
+ end
20
+
21
+ gemspec path: "../"
@@ -0,0 +1,17 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
6
+ gem "capybara"
7
+ gem "minitest-reporters", ">= 0.5.0"
8
+ gem "puma"
9
+ gem "rake"
10
+ gem "rdoc"
11
+ gem "shoulda"
12
+ gem "sprockets-rails"
13
+ gem "sqlite3", "~> 1.5.0"
14
+ gem "standardrb"
15
+ gem "rails", "~> 7.2.0"
16
+
17
+ gemspec path: "../"
@@ -0,0 +1,17 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
6
+ gem "capybara"
7
+ gem "minitest-reporters", ">= 0.5.0"
8
+ gem "puma"
9
+ gem "rake"
10
+ gem "rdoc"
11
+ gem "shoulda"
12
+ gem "sprockets-rails"
13
+ gem "sqlite3", "~> 2.1"
14
+ gem "standardrb"
15
+ gem "rails", "~> 8.0.0"
16
+
17
+ gemspec path: "../"
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module OTP
3
- VERSION = "0.7.1"
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
@@ -1,3 +1,5 @@
1
+ require "rqrcode"
2
+
1
3
  module DeviseOtpAuthenticatable
2
4
  module Controllers
3
5
  module Helpers
@@ -12,11 +14,8 @@ module DeviseOtpAuthenticatable
12
14
  #
13
15
  def otp_set_flash_message(key, kind, options = {})
14
16
  options[:scope] ||= "devise.otp.#{controller_name}"
15
- options[:default] = Array(options[:default]).unshift(kind.to_sym)
16
- options[:resource_name] = resource_name
17
- options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
18
- message = I18n.t("#{options[:resource_name]}.#{kind}", **options)
19
- flash[key] = message if message.present?
17
+
18
+ set_flash_message(key, kind, options)
20
19
  end
21
20
 
22
21
  def otp_t
@@ -122,33 +121,11 @@ module DeviseOtpAuthenticatable
122
121
  # returns the URL for the QR Code to initialize the Authenticator device
123
122
  #
124
123
  def otp_authenticator_token_image(resource)
125
- otp_authenticator_token_image_js(resource.otp_provisioning_uri)
126
- end
127
-
128
- private
129
-
130
- def otp_authenticator_token_image_js(otp_url)
131
124
  content_tag(:div, class: "qrcode-container") do
132
- content_tag(:div, id: "qrcode", class: "qrcode") do
133
- javascript_tag(%[
134
- new QRCode("qrcode", {
135
- text: "#{otp_url}",
136
- width: 256,
137
- height: 256,
138
- colorDark : "#000000",
139
- colorLight : "#ffffff",
140
- correctLevel : QRCode.CorrectLevel.H
141
- });
142
- ])
143
- end
125
+ raw RQRCode::QRCode.new(resource.otp_provisioning_uri).as_svg(:module_size => 5, :viewbox => true, :use_path => true)
144
126
  end
145
127
  end
146
128
 
147
- def otp_authenticator_token_image_google(otp_url)
148
- otp_url = Rack::Utils.escape(otp_url)
149
- url = "https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=#{otp_url}"
150
- image_tag(url, alt: "OTP Url QRCode")
151
- end
152
129
  end
153
130
  end
154
131
  end
@@ -1,4 +1,4 @@
1
- class DeviseOtpAddTo<%= table_name.camelize %> < ActiveRecord::Migration
1
+ class DeviseOtpAddTo<%= table_name.camelize %> < ActiveRecord::Migration[7.0]
2
2
  def self.up
3
3
  change_table :<%= table_name %> do |t|
4
4
  t.string :otp_auth_secret
@@ -11,4 +11,3 @@
11
11
  // GO AFTER THE REQUIRES BELOW.
12
12
  //
13
13
  //= require_tree .
14
- //= require devise-otp
@@ -8,6 +8,7 @@
8
8
  * You're free to add application-wide styles to this file and they'll appear at the top of the
9
9
  * compiled file, but it's generally better to create a new file per style scope.
10
10
  *
11
+ *= require devise-otp
11
12
  *= require_self
12
13
  *= require_tree .
13
14
  */
@@ -8,7 +8,13 @@
8
8
  </head>
9
9
  <body>
10
10
 
11
- <%= yield %>
11
+ <div id="alerts">
12
+ <% flash.keys.each do |key| %>
13
+ <%= content_tag :p, flash[key], :id => key %>
14
+ <% end %>
15
+ </div>
16
+
17
+ <%= yield %>
12
18
 
13
19
  </body>
14
20
  </html>
@@ -1,6 +1,6 @@
1
1
  Dummy::Application.routes.draw do
2
- devise_for :users
3
2
  devise_for :admins
3
+ devise_for :users
4
4
 
5
5
  resources :posts
6
6
  resources :admin_posts
@@ -1,4 +1,4 @@
1
- class CreateAdmins < ActiveRecord::Migration[7.1]
1
+ class CreateAdmins < ActiveRecord::Migration[5.0]
2
2
  def change
3
3
  create_table :admins do |t|
4
4
  t.string :name
@@ -23,6 +23,9 @@ class DisableTokenTest < ActionDispatch::IntegrationTest
23
23
  disable_otp
24
24
 
25
25
  assert page.has_content? "Disabled"
26
+ within "#alerts" do
27
+ assert page.has_content? 'Two-Factor Authentication has been disabled.'
28
+ end
26
29
 
27
30
  # logout
28
31
  sign_out
@@ -20,6 +20,10 @@ class EnableOtpFormTest < ActionDispatch::IntegrationTest
20
20
  assert_equal user_otp_token_path, current_path
21
21
  assert page.has_content?("Enabled")
22
22
 
23
+ within "#alerts" do
24
+ assert page.has_content? 'Your Two-Factor Authentication settings have been updated.'
25
+ end
26
+
23
27
  user.reload
24
28
  assert user.otp_enabled?
25
29
  end
@@ -37,6 +41,15 @@ class EnableOtpFormTest < ActionDispatch::IntegrationTest
37
41
 
38
42
  user.reload
39
43
  assert_not user.otp_enabled?
44
+
45
+ within "#alerts" do
46
+ assert page.has_content? 'The Confirmation Code you entered did not match the QR code shown below.'
47
+ end
48
+
49
+ visit "/"
50
+ within "#alerts" do
51
+ assert !page.has_content?('The Confirmation Code you entered did not match the QR code shown below.')
52
+ end
40
53
  end
41
54
 
42
55
  test "a user should not be able enable their OTP authentication with a blank confirmation code" do
@@ -50,6 +63,10 @@ class EnableOtpFormTest < ActionDispatch::IntegrationTest
50
63
 
51
64
  assert page.has_content?("To Enable Two-Factor Authentication")
52
65
 
66
+ within "#alerts" do
67
+ assert page.has_content? 'The Confirmation Code you entered did not match the QR code shown below.'
68
+ end
69
+
53
70
  user.reload
54
71
  assert_not user.otp_enabled?
55
72
  end
@@ -36,6 +36,9 @@ class PersistenceTest < ActionDispatch::IntegrationTest
36
36
 
37
37
  click_link("Trust this browser")
38
38
  assert_text "Your browser is trusted."
39
+ within "#alerts" do
40
+ assert page.has_content? 'Your device is now trusted.'
41
+ end
39
42
  sign_out
40
43
 
41
44
  sign_user_in
@@ -60,6 +60,15 @@ class RefreshTest < ActionDispatch::IntegrationTest
60
60
  fill_in "user_refresh_password", with: "12345670"
61
61
  click_button "Continue..."
62
62
  assert_equal refresh_user_otp_credential_path, current_path
63
+
64
+ within "#alerts" do
65
+ assert page.has_content? 'Sorry, you provided the wrong credentials.'
66
+ end
67
+
68
+ visit "/"
69
+ within "#alerts" do
70
+ assert !page.has_content?('Sorry, you provided the wrong credentials.')
71
+ end
63
72
  end
64
73
 
65
74
  test "user should be finally be able to access their settings, and just password is enough" do
@@ -23,6 +23,9 @@ class ResetTokenTest < ActionDispatch::IntegrationTest
23
23
  reset_otp
24
24
 
25
25
  assert_equal "/users/otp/token/edit", current_path
26
+ within "#alerts" do
27
+ assert page.has_content? 'Your token secret has been reset. Please confirm your new token secret below.'
28
+ end
26
29
  end
27
30
 
28
31
  test "generates new token secrets" do