devise-2fa 0.2.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +66 -41
- data/.gitignore +3 -0
- data/Appraisals +12 -0
- data/CHANGELOG.md +11 -0
- data/bin/rspec +2 -9
- data/bin/setup +3 -1
- data/devise_2fa.gemspec +6 -5
- data/lib/devise-2fa/version.rb +1 -1
- data/lib/devise_two_factorable/models/two_factorable.rb +9 -4
- data/spec/dummy/app/models/application_record.rb +6 -2
- data/spec/dummy/app/models/user.rb +37 -5
- data/spec/dummy/app/views/layouts/application.html.erb +0 -3
- data/spec/dummy/bin/setup +1 -16
- data/spec/dummy/config/application.rb +9 -2
- data/spec/dummy/config/database.yml +0 -10
- data/spec/dummy/config/environments/development.rb +0 -14
- data/spec/dummy/config/environments/test.rb +1 -14
- data/spec/dummy/config/initializers/devise.rb +5 -1
- data/spec/dummy/config/mongoid.yml +164 -0
- data/spec/dummy/config/routes.rb +6 -1
- data/spec/dummy/db/migrate/{20190312222952_devise_two_factor_add_to_users.rb → 20190625052821_devise_two_factor_add_to_users.rb} +1 -1
- data/spec/models/user_spec.rb +47 -2
- data/spec/spec_helper.rb +7 -3
- data/spec/system/token_spec.rb +1 -1
- metadata +34 -25
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -3
- data/spec/dummy/app/assets/javascripts/channels/.keep +0 -0
- data/spec/dummy/app/assets/stylesheets/application.css +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a34165f30cdc2d197acd726713f2ca7a6ed4ac2d4410aea31c10d4c12958e45d
|
|
4
|
+
data.tar.gz: ce5559076cac73dedcb0454982e8cd0f6dcd6d79ef2113b8e2426cc626e2cf27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 65d4138506168bbf1403791cb00573270781c30c54e9a7bf49b43c8145247188ac19fd7410558f86cc95c46986ecd5d78920725919210d0c24a2a2dbb36556b3
|
|
7
|
+
data.tar.gz: 8f2cc4f9f4f8215cc6b3e3cd0caf8e917608ac95ce3bbcfc6d371678fbaef8399f9cdccdc31cbe379319a244979278201c1607abc642c7c944a8f6275e6ed028
|
data/.circleci/config.yml
CHANGED
|
@@ -1,45 +1,70 @@
|
|
|
1
1
|
version: 2
|
|
2
|
+
|
|
3
|
+
build_config: &build_config
|
|
4
|
+
working_directory: ~/repo
|
|
5
|
+
steps:
|
|
6
|
+
- checkout
|
|
7
|
+
|
|
8
|
+
- restore_cache:
|
|
9
|
+
keys:
|
|
10
|
+
- v1-dependencies-{{ checksum "devise_2fa.gemspec" }}-{{ checksum "Appraisals" }}
|
|
11
|
+
- v1-dependencies-{{ checksum "devise_2fa.gemspec" }}
|
|
12
|
+
- v1-dependencies
|
|
13
|
+
|
|
14
|
+
- run: bin/setup
|
|
15
|
+
|
|
16
|
+
- save_cache:
|
|
17
|
+
paths:
|
|
18
|
+
- ./vendor/bundle
|
|
19
|
+
key: v1-dependencies-{{ checksum "devise_2fa.gemspec" }}-{{ checksum "Appraisals" }}
|
|
20
|
+
|
|
21
|
+
- run:
|
|
22
|
+
name: Setup Symmetric Encryption Config
|
|
23
|
+
command: |
|
|
24
|
+
cd spec/dummy/
|
|
25
|
+
symmetric-encryption -g
|
|
26
|
+
|
|
27
|
+
- run:
|
|
28
|
+
name: Run Tests
|
|
29
|
+
command: |
|
|
30
|
+
mkdir /tmp/test-results
|
|
31
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
|
|
32
|
+
circleci tests split --split-by=timings)"
|
|
33
|
+
|
|
34
|
+
bundle exec appraisal rspec \
|
|
35
|
+
--format progress \
|
|
36
|
+
--format RspecJunitFormatter \
|
|
37
|
+
--out /tmp/test-results/rspec.xml \
|
|
38
|
+
--format progress \
|
|
39
|
+
$TEST_FILES
|
|
40
|
+
|
|
41
|
+
- store_test_results:
|
|
42
|
+
path: /tmp/test-results
|
|
43
|
+
- store_artifacts:
|
|
44
|
+
path: /tmp/test-results
|
|
45
|
+
destination: test-results
|
|
46
|
+
|
|
2
47
|
jobs:
|
|
48
|
+
ruby-2.4:
|
|
49
|
+
<<: *build_config
|
|
50
|
+
docker:
|
|
51
|
+
- image: circleci/ruby:2.4-node-browsers
|
|
52
|
+
- image: circleci/mongo
|
|
53
|
+
ruby-2.5:
|
|
54
|
+
<<: *build_config
|
|
55
|
+
docker:
|
|
56
|
+
- image: circleci/ruby:2.5-node-browsers
|
|
57
|
+
- image: circleci/mongo
|
|
3
58
|
build:
|
|
59
|
+
<<: *build_config
|
|
4
60
|
docker:
|
|
5
|
-
- image: circleci/ruby:2.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- run:
|
|
17
|
-
name: install dependencies
|
|
18
|
-
command: |
|
|
19
|
-
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
|
20
|
-
|
|
21
|
-
- save_cache:
|
|
22
|
-
paths:
|
|
23
|
-
- ./vendor/bundle
|
|
24
|
-
key: v1-dependencies-{{ checksum "devise_2fa.gemspec" }}
|
|
25
|
-
|
|
26
|
-
- run: cd spec/dummy && bin/setup
|
|
27
|
-
|
|
28
|
-
- run:
|
|
29
|
-
name: run tests
|
|
30
|
-
command: |
|
|
31
|
-
mkdir /tmp/test-results
|
|
32
|
-
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
|
|
33
|
-
circleci tests split --split-by=timings)"
|
|
34
|
-
|
|
35
|
-
bundle exec rspec \
|
|
36
|
-
--format progress \
|
|
37
|
-
--out /tmp/test-results/rspec.xml \
|
|
38
|
-
--format progress \
|
|
39
|
-
$TEST_FILES
|
|
40
|
-
|
|
41
|
-
- store_test_results:
|
|
42
|
-
path: /tmp/test-results
|
|
43
|
-
- store_artifacts:
|
|
44
|
-
path: /tmp/test-results
|
|
45
|
-
destination: test-results
|
|
61
|
+
- image: circleci/ruby:2.6-node-browsers
|
|
62
|
+
- image: circleci/mongo
|
|
63
|
+
|
|
64
|
+
workflows:
|
|
65
|
+
version: 2
|
|
66
|
+
build:
|
|
67
|
+
jobs:
|
|
68
|
+
- ruby-2.4
|
|
69
|
+
- ruby-2.5
|
|
70
|
+
- build
|
data/.gitignore
CHANGED
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.4.0] - 2019-08-22
|
|
10
|
+
### Added
|
|
11
|
+
- Appraisal suite.
|
|
12
|
+
- Mongoid specs.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Refactors #validate_otp_token_with_drift from #15.
|
|
16
|
+
- Upgraded rotp dependency to ```~> 5.1```.
|
|
17
|
+
|
|
18
|
+
## [0.3.0] - REVOKED
|
|
19
|
+
|
|
9
20
|
## [0.2.1] - 2019-05-28
|
|
10
21
|
### Changed
|
|
11
22
|
- Relaxed Rails dependency to ```~> 6.1```.
|
data/bin/rspec
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
#!/
|
|
2
|
-
# frozen_string_literal: true
|
|
1
|
+
#!/bin/bash
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
load File.expand_path('../spring', __FILE__)
|
|
6
|
-
rescue LoadError => e
|
|
7
|
-
raise unless e.message.include?('spring')
|
|
8
|
-
end
|
|
9
|
-
require 'bundler/setup'
|
|
10
|
-
load Gem.bin_path('rspec-core', 'rspec')
|
|
3
|
+
bundle exec appraisal rspec
|
data/bin/setup
CHANGED
data/devise_2fa.gemspec
CHANGED
|
@@ -21,14 +21,15 @@ Gem::Specification.new do |gem|
|
|
|
21
21
|
gem.add_dependency "rails", ">= 4.1", "< 6.1"
|
|
22
22
|
|
|
23
23
|
gem.add_runtime_dependency 'devise', '~> 4.0'
|
|
24
|
-
gem.add_runtime_dependency 'rotp', '~>
|
|
24
|
+
gem.add_runtime_dependency 'rotp', '~> 5.1'
|
|
25
25
|
gem.add_runtime_dependency 'rqrcode', '~> 0.10.1'
|
|
26
26
|
gem.add_runtime_dependency 'symmetric-encryption', '~> 4.3.0'
|
|
27
27
|
|
|
28
|
-
gem.add_development_dependency '
|
|
29
|
-
gem.add_development_dependency 'selenium-webdriver'
|
|
30
|
-
gem.add_development_dependency 'rspec-rails'
|
|
28
|
+
gem.add_development_dependency 'appraisal'
|
|
31
29
|
gem.add_development_dependency 'capybara'
|
|
32
|
-
gem.add_development_dependency 'rspec'
|
|
33
30
|
gem.add_development_dependency 'pry'
|
|
31
|
+
gem.add_development_dependency 'rspec'
|
|
32
|
+
gem.add_development_dependency 'rspec-rails'
|
|
33
|
+
gem.add_development_dependency 'rspec_junit_formatter'
|
|
34
|
+
gem.add_development_dependency 'selenium-webdriver'
|
|
34
35
|
end
|
data/lib/devise-2fa/version.rb
CHANGED
|
@@ -117,10 +117,15 @@ module Devise::Models
|
|
|
117
117
|
private
|
|
118
118
|
|
|
119
119
|
def validate_otp_token_with_drift(token)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
time_based_otp.verify(
|
|
121
|
+
token,
|
|
122
|
+
drift_behind: drift.minutes.seconds,
|
|
123
|
+
at: Time.now + drift.minutes.seconds / 2
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def drift
|
|
128
|
+
self.class.otp_drift_window
|
|
124
129
|
end
|
|
125
130
|
|
|
126
131
|
def generate_otp_persistence_seed
|
|
@@ -1,6 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'symmetric_encryption'
|
|
4
|
+
|
|
5
|
+
if defined?(ActiveRecord)
|
|
6
|
+
class User < ApplicationRecord
|
|
7
|
+
devise :two_factorable, :database_authenticatable, :registerable,
|
|
8
|
+
:recoverable, :rememberable, :validatable
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
require 'mongoid'
|
|
12
|
+
class User
|
|
13
|
+
include Mongoid::Document
|
|
14
|
+
field :encrypted_otp_auth_secret, type: String, encrypted: true
|
|
15
|
+
field :encrypted_otp_recovery_secret, type: String, encrypted: true
|
|
16
|
+
field :otp_enabled, type: Boolean, default: false
|
|
17
|
+
field :otp_mandatory, type: Boolean, default: false
|
|
18
|
+
field :otp_enabled_on, type: DateTime
|
|
19
|
+
field :otp_failed_attempts, type: Integer, default: 0
|
|
20
|
+
field :otp_recovery_counter, type: Integer, default: 0
|
|
21
|
+
field :otp_persistence_seed, type: String
|
|
22
|
+
field :otp_session_challenge, type: String
|
|
23
|
+
field :otp_challenge_expires, type: DateTime
|
|
24
|
+
|
|
25
|
+
index({ otp_session_challenge: 1 }, background: true)
|
|
26
|
+
index({ otp_challenge_expires: 1 }, background: true)
|
|
27
|
+
|
|
28
|
+
devise :two_factorable, :database_authenticatable, :registerable,
|
|
29
|
+
:recoverable, :rememberable, :validatable
|
|
30
|
+
field :email, type: String, default: ''
|
|
31
|
+
field :encrypted_password, type: String, default: ''
|
|
32
|
+
field :reset_password_token, type: String
|
|
33
|
+
field :reset_password_sent_at, type: Time
|
|
34
|
+
field :remember_created_at, type: Time
|
|
35
|
+
field :name, type: String
|
|
36
|
+
field :phone, type: String
|
|
37
|
+
end
|
|
6
38
|
end
|
data/spec/dummy/bin/setup
CHANGED
|
@@ -5,21 +5,6 @@ include FileUtils
|
|
|
5
5
|
# path to your application root.
|
|
6
6
|
APP_ROOT = File.expand_path('..', __dir__)
|
|
7
7
|
|
|
8
|
-
def system!(*args)
|
|
9
|
-
system(*args) || abort("\n== Command #{args} failed ==")
|
|
10
|
-
end
|
|
11
|
-
|
|
12
8
|
chdir APP_ROOT do
|
|
13
|
-
|
|
14
|
-
system! 'gem install bundler --conservative'
|
|
15
|
-
system('bundle check') || system!('bundle install')
|
|
16
|
-
|
|
17
|
-
puts "\n== Preparing database =="
|
|
18
|
-
system! 'bin/rails db:setup'
|
|
19
|
-
|
|
20
|
-
puts "\n== Removing old logs and tempfiles =="
|
|
21
|
-
system! 'bin/rails log:clear tmp:clear'
|
|
22
|
-
|
|
23
|
-
puts "\n== Restarting application server =="
|
|
24
|
-
system! 'bin/rails restart'
|
|
9
|
+
system 'bin/rails db:setup 2> /dev/null'
|
|
25
10
|
end
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
require_relative 'boot'
|
|
2
2
|
|
|
3
|
-
require 'rails
|
|
3
|
+
require 'rails'
|
|
4
|
+
require 'active_model/railtie'
|
|
5
|
+
unless ENV['BUNDLE_GEMFILE'].include?('mongodb')
|
|
6
|
+
require 'active_record/railtie'
|
|
7
|
+
end
|
|
8
|
+
require 'action_controller/railtie'
|
|
9
|
+
require 'action_view/railtie'
|
|
10
|
+
require 'sprockets/railtie'
|
|
11
|
+
require 'rails/test_unit/railtie'
|
|
4
12
|
|
|
5
13
|
Bundler.require(*Rails.groups)
|
|
6
14
|
require 'devise-2fa'
|
|
@@ -11,4 +19,3 @@ module Dummy
|
|
|
11
19
|
config.load_defaults 5.0
|
|
12
20
|
end
|
|
13
21
|
end
|
|
14
|
-
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
# SQLite version 3.x
|
|
2
|
-
# gem install sqlite3
|
|
3
|
-
#
|
|
4
|
-
# Ensure the SQLite 3 gem is defined in your Gemfile
|
|
5
|
-
# gem 'sqlite3'
|
|
6
|
-
#
|
|
7
1
|
default: &default
|
|
8
2
|
adapter: sqlite3
|
|
9
3
|
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
|
@@ -19,7 +13,3 @@ development:
|
|
|
19
13
|
test:
|
|
20
14
|
<<: *default
|
|
21
15
|
database: db/test.sqlite3
|
|
22
|
-
|
|
23
|
-
production:
|
|
24
|
-
<<: *default
|
|
25
|
-
database: db/production.sqlite3
|
|
@@ -27,23 +27,9 @@ Rails.application.configure do
|
|
|
27
27
|
config.cache_store = :null_store
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
# Store uploaded files on the local file system (see config/storage.yml for options)
|
|
31
|
-
config.active_storage.service = :local
|
|
32
|
-
|
|
33
|
-
# Don't care if the mailer can't send.
|
|
34
|
-
config.action_mailer.raise_delivery_errors = false
|
|
35
|
-
|
|
36
|
-
config.action_mailer.perform_caching = false
|
|
37
|
-
|
|
38
30
|
# Print deprecation notices to the Rails logger.
|
|
39
31
|
config.active_support.deprecation = :log
|
|
40
32
|
|
|
41
|
-
# Raise an error on page load if there are pending migrations.
|
|
42
|
-
config.active_record.migration_error = :page_load
|
|
43
|
-
|
|
44
|
-
# Highlight code that triggered database queries in logs.
|
|
45
|
-
config.active_record.verbose_query_logs = true
|
|
46
|
-
|
|
47
33
|
# Debug mode disables concatenation and preprocessing of assets.
|
|
48
34
|
# This option may cause significant delays in view rendering with a large
|
|
49
35
|
# number of complex assets.
|
|
@@ -10,7 +10,7 @@ Rails.application.configure do
|
|
|
10
10
|
# Do not eager load code on boot. This avoids loading your whole application
|
|
11
11
|
# just for the purpose of running a single test. If you are using a tool that
|
|
12
12
|
# preloads Rails for running tests, you may have to set it to true.
|
|
13
|
-
config.eager_load =
|
|
13
|
+
config.eager_load = true
|
|
14
14
|
|
|
15
15
|
# Configure public file server for tests with Cache-Control for performance
|
|
16
16
|
config.public_file_server.enabled = true
|
|
@@ -28,19 +28,6 @@ Rails.application.configure do
|
|
|
28
28
|
# Disable request forgery protection in test environment
|
|
29
29
|
config.action_controller.allow_forgery_protection = false
|
|
30
30
|
|
|
31
|
-
# Store uploaded files on the local file system in a temporary directory
|
|
32
|
-
config.active_storage.service = :test
|
|
33
|
-
|
|
34
|
-
config.action_mailer.perform_caching = false
|
|
35
|
-
|
|
36
|
-
# Tell Action Mailer not to deliver emails to the real world
|
|
37
|
-
# The :test delivery method accumulates sent emails in the
|
|
38
|
-
# ActionMailer::Base.deliveries array.
|
|
39
|
-
config.action_mailer.delivery_method = :test
|
|
40
|
-
|
|
41
31
|
# Print deprecation notices to the stderr
|
|
42
32
|
config.active_support.deprecation = :stderr
|
|
43
|
-
|
|
44
|
-
# Raises error for missing translations
|
|
45
|
-
# config.action_view.raise_on_missing_translations = true
|
|
46
33
|
end
|
|
@@ -30,7 +30,11 @@ Devise.setup do |config|
|
|
|
30
30
|
# Load and configure the ORM. Supports :active_record (default) and
|
|
31
31
|
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
|
32
32
|
# available as additional gems.
|
|
33
|
-
|
|
33
|
+
if defined?(ActiveRecord)
|
|
34
|
+
require 'devise/orm/active_record'
|
|
35
|
+
else
|
|
36
|
+
require 'devise/orm/mongoid'
|
|
37
|
+
end
|
|
34
38
|
|
|
35
39
|
# ==> Configuration for any authentication mechanism
|
|
36
40
|
# Configure which keys are used when authenticating a user. The default is
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
development:
|
|
2
|
+
# Configure available database clients. (required)
|
|
3
|
+
clients:
|
|
4
|
+
# Defines the default client. (required)
|
|
5
|
+
default:
|
|
6
|
+
# Defines the name of the default database that Mongoid can connect to.
|
|
7
|
+
# (required).
|
|
8
|
+
database: dummy_development
|
|
9
|
+
# Provides the hosts the default client can connect to. Must be an array
|
|
10
|
+
# of host:port pairs. (required)
|
|
11
|
+
hosts:
|
|
12
|
+
- localhost:27017
|
|
13
|
+
options:
|
|
14
|
+
# Note that all options listed below are Ruby driver client options (the mongo gem).
|
|
15
|
+
# Please refer to the driver documentation of the version of the mongo gem you are using
|
|
16
|
+
# for the most up-to-date list of options.
|
|
17
|
+
#
|
|
18
|
+
# Change the default write concern. (default = { w: 1 })
|
|
19
|
+
# write:
|
|
20
|
+
# w: 1
|
|
21
|
+
|
|
22
|
+
# Change the default read preference. Valid options for mode are: :secondary,
|
|
23
|
+
# :secondary_preferred, :primary, :primary_preferred, :nearest
|
|
24
|
+
# (default: primary)
|
|
25
|
+
# read:
|
|
26
|
+
# mode: :secondary_preferred
|
|
27
|
+
# tag_sets:
|
|
28
|
+
# - use: web
|
|
29
|
+
|
|
30
|
+
# The name of the user for authentication.
|
|
31
|
+
# user: 'user'
|
|
32
|
+
|
|
33
|
+
# The password of the user for authentication.
|
|
34
|
+
# password: 'password'
|
|
35
|
+
|
|
36
|
+
# The user's database roles.
|
|
37
|
+
# roles:
|
|
38
|
+
# - 'dbOwner'
|
|
39
|
+
|
|
40
|
+
# Change the default authentication mechanism. Valid options are: :scram,
|
|
41
|
+
# :mongodb_cr, :mongodb_x509, and :plain. Note that all authentication
|
|
42
|
+
# mechanisms require username and password, with the exception of :mongodb_x509.
|
|
43
|
+
# Default on mongoDB 3.0 is :scram, default on 2.4 and 2.6 is :plain.
|
|
44
|
+
# auth_mech: :scram
|
|
45
|
+
|
|
46
|
+
# The database or source to authenticate the user against.
|
|
47
|
+
# (default: the database specified above or admin)
|
|
48
|
+
# auth_source: admin
|
|
49
|
+
|
|
50
|
+
# Force a the driver cluster to behave in a certain manner instead of auto-
|
|
51
|
+
# discovering. Can be one of: :direct, :replica_set, :sharded. Set to :direct
|
|
52
|
+
# when connecting to hidden members of a replica set.
|
|
53
|
+
# connect: :direct
|
|
54
|
+
|
|
55
|
+
# Changes the default time in seconds the server monitors refresh their status
|
|
56
|
+
# via ismaster commands. (default: 10)
|
|
57
|
+
# heartbeat_frequency: 10
|
|
58
|
+
|
|
59
|
+
# The time in seconds for selecting servers for a near read preference. (default: 0.015)
|
|
60
|
+
# local_threshold: 0.015
|
|
61
|
+
|
|
62
|
+
# The timeout in seconds for selecting a server for an operation. (default: 30)
|
|
63
|
+
# server_selection_timeout: 30
|
|
64
|
+
|
|
65
|
+
# The maximum number of connections in the connection pool. (default: 5)
|
|
66
|
+
# max_pool_size: 5
|
|
67
|
+
|
|
68
|
+
# The minimum number of connections in the connection pool. (default: 1)
|
|
69
|
+
# min_pool_size: 1
|
|
70
|
+
|
|
71
|
+
# The time to wait, in seconds, in the connection pool for a connection
|
|
72
|
+
# to be checked in before timing out. (default: 5)
|
|
73
|
+
# wait_queue_timeout: 5
|
|
74
|
+
|
|
75
|
+
# The time to wait to establish a connection before timing out, in seconds.
|
|
76
|
+
# (default: 5)
|
|
77
|
+
# connect_timeout: 5
|
|
78
|
+
|
|
79
|
+
# The timeout to wait to execute operations on a socket before raising an error.
|
|
80
|
+
# (default: 5)
|
|
81
|
+
# socket_timeout: 5
|
|
82
|
+
|
|
83
|
+
# The name of the replica set to connect to. Servers provided as seeds that do
|
|
84
|
+
# not belong to this replica set will be ignored.
|
|
85
|
+
# replica_set: name
|
|
86
|
+
|
|
87
|
+
# Whether to connect to the servers via ssl. (default: false)
|
|
88
|
+
# ssl: true
|
|
89
|
+
|
|
90
|
+
# The certificate file used to identify the connection against MongoDB.
|
|
91
|
+
# ssl_cert: /path/to/my.cert
|
|
92
|
+
|
|
93
|
+
# The private keyfile used to identify the connection against MongoDB.
|
|
94
|
+
# Note that even if the key is stored in the same file as the certificate,
|
|
95
|
+
# both need to be explicitly specified.
|
|
96
|
+
# ssl_key: /path/to/my.key
|
|
97
|
+
|
|
98
|
+
# A passphrase for the private key.
|
|
99
|
+
# ssl_key_pass_phrase: password
|
|
100
|
+
|
|
101
|
+
# Whether or not to do peer certification validation. (default: true)
|
|
102
|
+
# ssl_verify: true
|
|
103
|
+
|
|
104
|
+
# The file containing a set of concatenated certification authority certifications
|
|
105
|
+
# used to validate certs passed from the other end of the connection.
|
|
106
|
+
# ssl_ca_cert: /path/to/ca.cert
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Configure Mongoid specific options. (optional)
|
|
110
|
+
options:
|
|
111
|
+
# Includes the root model name in json serialization. (default: false)
|
|
112
|
+
# include_root_in_json: false
|
|
113
|
+
|
|
114
|
+
# Include the _type field in serialization. (default: false)
|
|
115
|
+
# include_type_for_serialization: false
|
|
116
|
+
|
|
117
|
+
# Preload all models in development, needed when models use
|
|
118
|
+
# inheritance. (default: false)
|
|
119
|
+
# preload_models: false
|
|
120
|
+
|
|
121
|
+
# Raise an error when performing a #find and the document is not found.
|
|
122
|
+
# (default: true)
|
|
123
|
+
# raise_not_found_error: true
|
|
124
|
+
|
|
125
|
+
# Raise an error when defining a scope with the same name as an
|
|
126
|
+
# existing method. (default: false)
|
|
127
|
+
# scope_overwrite_exception: false
|
|
128
|
+
|
|
129
|
+
# Raise an error when defining a field with the same name as an
|
|
130
|
+
# existing method. (default: false)
|
|
131
|
+
# duplicate_fields_exception: false
|
|
132
|
+
|
|
133
|
+
# Use Active Support's time zone in conversions. (default: true)
|
|
134
|
+
# use_activesupport_time_zone: true
|
|
135
|
+
|
|
136
|
+
# Ensure all times are UTC in the app side. (default: false)
|
|
137
|
+
# use_utc: false
|
|
138
|
+
|
|
139
|
+
# Set the Mongoid and Ruby driver log levels when not in a Rails
|
|
140
|
+
# environment. The Mongoid logger will be set to the Rails logger
|
|
141
|
+
# otherwise.(default: :info)
|
|
142
|
+
# log_level: :info
|
|
143
|
+
|
|
144
|
+
# Control whether `belongs_to` association is required. By default
|
|
145
|
+
# `belongs_to` will trigger a validation error if the association
|
|
146
|
+
# is not present. (default: true)
|
|
147
|
+
# belongs_to_required_by_default: true
|
|
148
|
+
|
|
149
|
+
# Application name that is printed to the mongodb logs upon establishing a
|
|
150
|
+
# connection in server versions >= 3.4. Note that the name cannot exceed 128 bytes.
|
|
151
|
+
# app_name: MyApplicationName
|
|
152
|
+
|
|
153
|
+
# Use background indexes by default if `background` option not specified. (default: false)
|
|
154
|
+
# background_indexing: false
|
|
155
|
+
test:
|
|
156
|
+
clients:
|
|
157
|
+
default:
|
|
158
|
+
database: dummy_test
|
|
159
|
+
hosts:
|
|
160
|
+
- localhost:27017
|
|
161
|
+
options:
|
|
162
|
+
read:
|
|
163
|
+
mode: :primary
|
|
164
|
+
max_pool_size: 1
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/models/user_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
RSpec.describe User, type: :model do
|
|
6
|
-
subject
|
|
6
|
+
subject(:user) { User.create(email: 'mb@geemail.com', password: 'iwantabigmac1') }
|
|
7
7
|
it 'is valid' do
|
|
8
8
|
expect(user).to be_valid
|
|
9
9
|
end
|
|
@@ -23,11 +23,56 @@ RSpec.describe User, type: :model do
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
describe '#password' do
|
|
26
|
-
subject(:user) { User.new(email: 'mb@geemail.com')}
|
|
26
|
+
subject(:user) { User.new(email: 'mb@geemail.com') }
|
|
27
27
|
|
|
28
28
|
it 'is required' do
|
|
29
29
|
expect(user).to be_invalid
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
|
+
|
|
34
|
+
describe '#validate_otp_token' do
|
|
35
|
+
context 'when otp_drift_window is 3 minutes (default)' do
|
|
36
|
+
let(:user_rotp) { ROTP::TOTP.new(user.otp_auth_secret) }
|
|
37
|
+
let(:control_time) { Time.now }
|
|
38
|
+
let(:token_time) { control_time }
|
|
39
|
+
|
|
40
|
+
before do
|
|
41
|
+
Devise.otp_drift_window = 3
|
|
42
|
+
allow(Time).to receive(:now).and_return(control_time)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "when token's time is 2 minutes before current time" do
|
|
46
|
+
let(:token_time) { control_time - 2.minutes }
|
|
47
|
+
|
|
48
|
+
it do
|
|
49
|
+
expect(user.validate_otp_token(user_rotp.at(token_time))).to be_falsey
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "when token's time is 1 minute before current time" do
|
|
54
|
+
let(:token_time) { control_time - 1.minute }
|
|
55
|
+
|
|
56
|
+
it do
|
|
57
|
+
expect(user.validate_otp_token(user_rotp.at(token_time))).to be_truthy
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when token's time is 1 minute after current time" do
|
|
62
|
+
let(:token_time) { control_time + 1.minute }
|
|
63
|
+
|
|
64
|
+
it do
|
|
65
|
+
expect(user.validate_otp_token(user_rotp.at(token_time))).to be_truthy
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context "when token's time is 2 minutes after current time" do
|
|
70
|
+
let(:token_time) { control_time + 2.minute }
|
|
71
|
+
|
|
72
|
+
it do
|
|
73
|
+
expect(user.validate_otp_token(user_rotp.at(token_time))).to be_falsey
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
33
78
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
ENV[
|
|
3
|
+
ENV['RAILS_ENV'] ||= 'test'
|
|
4
4
|
|
|
5
|
-
require
|
|
6
|
-
require "dummy/config/application"
|
|
5
|
+
require 'dummy/config/application'
|
|
7
6
|
require 'bundler/setup'
|
|
8
7
|
require 'rspec/rails'
|
|
9
8
|
|
|
@@ -24,6 +23,11 @@ RSpec.configure do |config|
|
|
|
24
23
|
config.before(:each, type: :system) do
|
|
25
24
|
driven_by :rack_test
|
|
26
25
|
end
|
|
26
|
+
if defined? Mongoid
|
|
27
|
+
config.before :each do
|
|
28
|
+
Mongoid.purge!
|
|
29
|
+
end
|
|
30
|
+
end
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
|
data/spec/system/token_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
RSpec.describe 'Tokens' do
|
|
6
|
-
subject
|
|
6
|
+
subject(:user) { User.create(email: 'mb@geemail.com', password: 'iwantabigmac1') }
|
|
7
7
|
|
|
8
8
|
it 'can be disabled by a user after successfully enabling' do
|
|
9
9
|
enable_otp_and_sign_in user
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise-2fa
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William A. Todd
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-
|
|
11
|
+
date: 2019-08-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -50,14 +50,14 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
53
|
+
version: '5.1'
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '5.1'
|
|
61
61
|
- !ruby/object:Gem::Dependency
|
|
62
62
|
name: rqrcode
|
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -87,21 +87,21 @@ dependencies:
|
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
88
|
version: 4.3.0
|
|
89
89
|
- !ruby/object:Gem::Dependency
|
|
90
|
-
name:
|
|
90
|
+
name: appraisal
|
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
|
-
- - "
|
|
93
|
+
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version:
|
|
95
|
+
version: '0'
|
|
96
96
|
type: :development
|
|
97
97
|
prerelease: false
|
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
|
-
- - "
|
|
100
|
+
- - ">="
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version:
|
|
102
|
+
version: '0'
|
|
103
103
|
- !ruby/object:Gem::Dependency
|
|
104
|
-
name:
|
|
104
|
+
name: capybara
|
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
|
107
107
|
- - ">="
|
|
@@ -115,7 +115,7 @@ dependencies:
|
|
|
115
115
|
- !ruby/object:Gem::Version
|
|
116
116
|
version: '0'
|
|
117
117
|
- !ruby/object:Gem::Dependency
|
|
118
|
-
name:
|
|
118
|
+
name: pry
|
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
|
120
120
|
requirements:
|
|
121
121
|
- - ">="
|
|
@@ -129,7 +129,7 @@ dependencies:
|
|
|
129
129
|
- !ruby/object:Gem::Version
|
|
130
130
|
version: '0'
|
|
131
131
|
- !ruby/object:Gem::Dependency
|
|
132
|
-
name:
|
|
132
|
+
name: rspec
|
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
|
134
134
|
requirements:
|
|
135
135
|
- - ">="
|
|
@@ -143,7 +143,7 @@ dependencies:
|
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
144
|
version: '0'
|
|
145
145
|
- !ruby/object:Gem::Dependency
|
|
146
|
-
name: rspec
|
|
146
|
+
name: rspec-rails
|
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
|
148
148
|
requirements:
|
|
149
149
|
- - ">="
|
|
@@ -157,7 +157,21 @@ dependencies:
|
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
158
|
version: '0'
|
|
159
159
|
- !ruby/object:Gem::Dependency
|
|
160
|
-
name:
|
|
160
|
+
name: rspec_junit_formatter
|
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0'
|
|
166
|
+
type: :development
|
|
167
|
+
prerelease: false
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '0'
|
|
173
|
+
- !ruby/object:Gem::Dependency
|
|
174
|
+
name: selenium-webdriver
|
|
161
175
|
requirement: !ruby/object:Gem::Requirement
|
|
162
176
|
requirements:
|
|
163
177
|
- - ">="
|
|
@@ -181,6 +195,7 @@ files:
|
|
|
181
195
|
- ".gitignore"
|
|
182
196
|
- ".hound.yml"
|
|
183
197
|
- ".ruby-style.yml"
|
|
198
|
+
- Appraisals
|
|
184
199
|
- CHANGELOG.md
|
|
185
200
|
- Gemfile
|
|
186
201
|
- LICENSE
|
|
@@ -217,10 +232,6 @@ files:
|
|
|
217
232
|
- lib/generators/devise_two_factor/views_generator.rb
|
|
218
233
|
- lib/generators/mongoid/devise_two_factor_generator.rb
|
|
219
234
|
- spec/dummy/Rakefile
|
|
220
|
-
- spec/dummy/app/assets/images/.keep
|
|
221
|
-
- spec/dummy/app/assets/javascripts/application.js
|
|
222
|
-
- spec/dummy/app/assets/javascripts/channels/.keep
|
|
223
|
-
- spec/dummy/app/assets/stylesheets/application.css
|
|
224
235
|
- spec/dummy/app/controllers/application_controller.rb
|
|
225
236
|
- spec/dummy/app/controllers/concerns/.keep
|
|
226
237
|
- spec/dummy/app/helpers/application_helper.rb
|
|
@@ -253,12 +264,13 @@ files:
|
|
|
253
264
|
- spec/dummy/config/locales/devise.en.yml
|
|
254
265
|
- spec/dummy/config/locales/devise.two_factor.en.yml
|
|
255
266
|
- spec/dummy/config/locales/en.yml
|
|
267
|
+
- spec/dummy/config/mongoid.yml
|
|
256
268
|
- spec/dummy/config/puma.rb
|
|
257
269
|
- spec/dummy/config/routes.rb
|
|
258
270
|
- spec/dummy/config/spring.rb
|
|
259
271
|
- spec/dummy/config/storage.yml
|
|
260
272
|
- spec/dummy/db/migrate/20190311184605_devise_create_users.rb
|
|
261
|
-
- spec/dummy/db/migrate/
|
|
273
|
+
- spec/dummy/db/migrate/20190625052821_devise_two_factor_add_to_users.rb
|
|
262
274
|
- spec/dummy/db/schema.rb
|
|
263
275
|
- spec/dummy/lib/assets/.keep
|
|
264
276
|
- spec/dummy/package.json
|
|
@@ -294,16 +306,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
294
306
|
- !ruby/object:Gem::Version
|
|
295
307
|
version: '0'
|
|
296
308
|
requirements: []
|
|
297
|
-
rubygems_version: 3.0.
|
|
309
|
+
rubygems_version: 3.0.4
|
|
298
310
|
signing_key:
|
|
299
311
|
specification_version: 4
|
|
300
312
|
summary: Includes ActiveRecord and Mongoid ORM support
|
|
301
313
|
test_files:
|
|
302
314
|
- spec/dummy/Rakefile
|
|
303
|
-
- spec/dummy/app/assets/images/.keep
|
|
304
|
-
- spec/dummy/app/assets/javascripts/application.js
|
|
305
|
-
- spec/dummy/app/assets/javascripts/channels/.keep
|
|
306
|
-
- spec/dummy/app/assets/stylesheets/application.css
|
|
307
315
|
- spec/dummy/app/controllers/application_controller.rb
|
|
308
316
|
- spec/dummy/app/controllers/concerns/.keep
|
|
309
317
|
- spec/dummy/app/helpers/application_helper.rb
|
|
@@ -336,12 +344,13 @@ test_files:
|
|
|
336
344
|
- spec/dummy/config/locales/devise.en.yml
|
|
337
345
|
- spec/dummy/config/locales/devise.two_factor.en.yml
|
|
338
346
|
- spec/dummy/config/locales/en.yml
|
|
347
|
+
- spec/dummy/config/mongoid.yml
|
|
339
348
|
- spec/dummy/config/puma.rb
|
|
340
349
|
- spec/dummy/config/routes.rb
|
|
341
350
|
- spec/dummy/config/spring.rb
|
|
342
351
|
- spec/dummy/config/storage.yml
|
|
343
352
|
- spec/dummy/db/migrate/20190311184605_devise_create_users.rb
|
|
344
|
-
- spec/dummy/db/migrate/
|
|
353
|
+
- spec/dummy/db/migrate/20190625052821_devise_two_factor_add_to_users.rb
|
|
345
354
|
- spec/dummy/db/schema.rb
|
|
346
355
|
- spec/dummy/lib/assets/.keep
|
|
347
356
|
- spec/dummy/package.json
|
|
File without changes
|
|
File without changes
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
-
* listed below.
|
|
4
|
-
*
|
|
5
|
-
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
-
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
-
*
|
|
8
|
-
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
-
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
|
10
|
-
* files in this directory. Styles in this file should be added after the last require_* statement.
|
|
11
|
-
* It is generally better to create a new file per style scope.
|
|
12
|
-
*
|
|
13
|
-
*= require_tree .
|
|
14
|
-
*= require_self
|
|
15
|
-
*/
|