devise-security 0.14.1 → 0.14.2
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/README.md +1 -1
- data/Rakefile +1 -1
- data/gemfiles/rails_6.0_beta.gemfile +1 -1
- data/lib/devise-security/hooks/session_limitable.rb +12 -7
- data/lib/devise-security/models/compatibility.rb +2 -2
- data/lib/devise-security/models/compatibility/{active_record.rb → active_record_patch.rb} +12 -1
- data/lib/devise-security/models/compatibility/{mongoid.rb → mongoid_patch.rb} +11 -1
- data/lib/devise-security/models/session_limitable.rb +9 -3
- data/lib/devise-security/version.rb +1 -1
- data/test/{test_captcha_controller.rb → controllers/test_captcha_controller.rb} +0 -0
- data/test/{test_password_expired_controller.rb → controllers/test_password_expired_controller.rb} +0 -0
- data/test/{test_security_question_controller.rb → controllers/test_security_question_controller.rb} +0 -0
- data/test/dummy/app/controllers/widgets_controller.rb +6 -0
- data/test/dummy/app/models/user.rb +8 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/dummy/db/migrate/20120508165529_create_tables.rb +10 -1
- data/test/integration/test_session_limitable_workflow.rb +67 -0
- data/test/support/integration_helpers.rb +47 -0
- data/test/test_compatibility.rb +13 -0
- data/test/test_helper.rb +11 -2
- data/test/test_session_limitable.rb +31 -0
- metadata +20 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aa65f547b5acbc4207678cda6b4af888f94f3c18a7ebb1ccd80888433cf350f
|
4
|
+
data.tar.gz: ce3b96b475d683ba121c3db9477915c44c52ac27c9244a54f5c613e76a0e86e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 540d6e0534dd9c37d28e7281ada99959d73f6afb0de030f406305e689c237afda6ea94fc3f84f4392c4a5cea2243191aa1aaae4bf0f9e77efb41a41cff2e8497
|
7
|
+
data.tar.gz: 6064b218564eb7c9b3d8b849185d4fe3bbd49c466e47716a6ee666dcbc5f02f27d7015dde4f32238c95f6189b32516afcf3101c2dea0cb0bd78e9f9bd2d70cfd
|
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# After each sign in, update unique_session_id.
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# not trigger it.
|
3
|
+
# After each sign in, update unique_session_id. This is only triggered when the
|
4
|
+
# user is explicitly set (with set_user) and on authentication. Retrieving the
|
5
|
+
# user from session (:fetch) does not trigger it.
|
7
6
|
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
|
8
7
|
if record.respond_to?(:update_unique_session_id!) && warden.authenticated?(options[:scope])
|
9
8
|
unique_session_id = Devise.friendly_token
|
@@ -12,15 +11,21 @@ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
|
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
|
-
# Each time a record is fetched from session we check if a new session from
|
16
|
-
# browser was opened for the record or not, based on a unique session
|
17
|
-
# If so, the old account is logged out and redirected to the sign in
|
14
|
+
# Each time a record is fetched from session we check if a new session from
|
15
|
+
# another browser was opened for the record or not, based on a unique session
|
16
|
+
# identifier. If so, the old account is logged out and redirected to the sign in
|
17
|
+
# page on the next request.
|
18
18
|
Warden::Manager.after_set_user only: :fetch do |record, warden, options|
|
19
19
|
scope = options[:scope]
|
20
20
|
env = warden.request.env
|
21
21
|
|
22
22
|
if record.respond_to?(:unique_session_id) && warden.authenticated?(scope) && options[:store] != false
|
23
23
|
if record.unique_session_id != warden.session(scope)['unique_session_id'] && !env['devise.skip_session_limitable']
|
24
|
+
Rails.logger.warn {
|
25
|
+
"[devise-security][session_limitable] session id mismatch: "\
|
26
|
+
"expected=#{record.unique_session_id.inspect} "\
|
27
|
+
"actual=#{warden.session(scope)['unique_session_id'].inspect}"
|
28
|
+
}
|
24
29
|
warden.raw_session.clear
|
25
30
|
warden.logout(scope)
|
26
31
|
throw :warden, scope: scope, message: :session_limited
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "compatibility/#{DEVISE_ORM}"
|
3
|
+
require_relative "compatibility/#{DEVISE_ORM}_patch"
|
4
4
|
|
5
5
|
module Devise
|
6
6
|
module Models
|
@@ -9,7 +9,7 @@ module Devise
|
|
9
9
|
# and/or older versions of ORMs.
|
10
10
|
module Compatibility
|
11
11
|
extend ActiveSupport::Concern
|
12
|
-
include "Devise::Models::Compatibility::#{DEVISE_ORM.to_s.classify}".constantize
|
12
|
+
include "Devise::Models::Compatibility::#{DEVISE_ORM.to_s.classify}Patch".constantize
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Devise
|
2
2
|
module Models
|
3
3
|
module Compatibility
|
4
|
-
|
4
|
+
|
5
|
+
class NotPersistedError < ActiveRecord::ActiveRecordError; end
|
6
|
+
|
7
|
+
module ActiveRecordPatch
|
5
8
|
extend ActiveSupport::Concern
|
6
9
|
unless Devise.activerecord51?
|
7
10
|
# When the record was saved, was the +encrypted_password+ changed?
|
@@ -23,6 +26,14 @@ module Devise
|
|
23
26
|
changed_attributes['encrypted_password'].present?
|
24
27
|
end
|
25
28
|
end
|
29
|
+
|
30
|
+
# Updates the record with the value and does not trigger validations or callbacks
|
31
|
+
# @param name [Symbol] attribute to update
|
32
|
+
# @param value [String] value to set
|
33
|
+
def update_attribute_without_validatons_or_callbacks(name, value)
|
34
|
+
update_column(name, value)
|
35
|
+
end
|
36
|
+
|
26
37
|
end
|
27
38
|
end
|
28
39
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Devise
|
2
2
|
module Models
|
3
3
|
module Compatibility
|
4
|
-
|
4
|
+
|
5
|
+
class NotPersistedError < Mongoid::Errors::MongoidError; end
|
6
|
+
|
7
|
+
module MongoidPatch
|
5
8
|
extend ActiveSupport::Concern
|
6
9
|
|
7
10
|
# Will saving this record change the +email+ attribute?
|
@@ -15,6 +18,13 @@ module Devise
|
|
15
18
|
def will_save_change_to_encrypted_password?
|
16
19
|
changed.include? 'encrypted_password'
|
17
20
|
end
|
21
|
+
|
22
|
+
# Updates the document with the value and does not trigger validations or callbacks
|
23
|
+
# @param name [Symbol] attribute to update
|
24
|
+
# @param value [String] value to set
|
25
|
+
def update_attribute_without_validatons_or_callbacks(name, value)
|
26
|
+
set(Hash[*[name, value]])
|
27
|
+
end
|
18
28
|
end
|
19
29
|
end
|
20
30
|
end
|
@@ -12,10 +12,16 @@ module Devise
|
|
12
12
|
module SessionLimitable
|
13
13
|
extend ActiveSupport::Concern
|
14
14
|
|
15
|
+
# Update the unique_session_id on the model. This will be checked in
|
16
|
+
# the Warden after_set_user hook in {file:devise-security/hooks/session_limitable}
|
17
|
+
# @param unique_session_id [String]
|
18
|
+
# @return [void]
|
19
|
+
# @raise [Devise::Models::Compatibility::NotPersistedError] if record is unsaved
|
15
20
|
def update_unique_session_id!(unique_session_id)
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
raise Devise::Models::Compatibility::NotPersistedError, 'cannot update a new record' unless persisted?
|
22
|
+
update_attribute_without_validatons_or_callbacks(:unique_session_id, unique_session_id).tap do
|
23
|
+
Rails.logger.debug { "[devise-security][session_limitable] unique_session_id=#{unique_session_id}"}
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
end
|
File without changes
|
data/test/{test_password_expired_controller.rb → controllers/test_password_expired_controller.rb}
RENAMED
File without changes
|
data/test/{test_security_question_controller.rb → controllers/test_security_question_controller.rb}
RENAMED
File without changes
|
@@ -25,5 +25,13 @@ class User < ApplicationRecord
|
|
25
25
|
if DEVISE_ORM == :mongoid
|
26
26
|
require './test/dummy/app/models/mongoid/mappings'
|
27
27
|
include ::Mongoid::Mappings
|
28
|
+
|
29
|
+
def some_method_calling_mongoid
|
30
|
+
Mongoid.logger
|
31
|
+
end
|
32
|
+
elsif DEVISE_ORM == :active_record
|
33
|
+
def some_method_calling_active_record
|
34
|
+
ActiveRecord::Base.transaction {}
|
35
|
+
end
|
28
36
|
end
|
29
37
|
end
|
data/test/dummy/config/routes.rb
CHANGED
@@ -5,13 +5,22 @@ class CreateTables < MIGRATION_CLASS
|
|
5
5
|
create_table :users do |t|
|
6
6
|
t.string :username
|
7
7
|
t.string :facebook_token
|
8
|
-
|
8
|
+
|
9
|
+
# session_limitable
|
10
|
+
t.string :unique_session_id
|
9
11
|
|
10
12
|
## Database authenticatable
|
11
13
|
t.string :email, null: false, default: ''
|
12
14
|
t.string :encrypted_password, null: false, default: ''
|
13
15
|
|
14
16
|
t.datetime :password_changed_at
|
17
|
+
|
18
|
+
t.datetime :current_sign_in_at
|
19
|
+
t.datetime :last_sign_in_at
|
20
|
+
t.string :current_sign_in_ip
|
21
|
+
t.string :last_sign_in_ip
|
22
|
+
t.integer :sign_in_count, default: 0
|
23
|
+
t.integer :failed_attempts, default: 0
|
15
24
|
t.timestamps null: false
|
16
25
|
end
|
17
26
|
add_index :users, :password_changed_at
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestSessionLimitableWorkflow < ActionDispatch::IntegrationTest
|
4
|
+
include IntegrationHelpers
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@user = User.create!(password: 'passWord1',
|
8
|
+
password_confirmation: 'passWord1',
|
9
|
+
email: 'bob@microsoft.com')
|
10
|
+
@user.confirm
|
11
|
+
end
|
12
|
+
|
13
|
+
test 'failed login' do
|
14
|
+
assert_nil @user.unique_session_id
|
15
|
+
|
16
|
+
open_session do |session|
|
17
|
+
failed_sign_in(@user, session)
|
18
|
+
session.assert_response(:success)
|
19
|
+
assert_equal session.flash[:alert], I18n.t('devise.failure.invalid', authentication_keys: 'Email')
|
20
|
+
assert_nil @user.reload.unique_session_id
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'successful login' do
|
25
|
+
assert_nil @user.unique_session_id
|
26
|
+
|
27
|
+
open_session do |session|
|
28
|
+
sign_in(@user, session)
|
29
|
+
session.assert_redirected_to '/'
|
30
|
+
session.get widgets_path
|
31
|
+
session.assert_response(:success)
|
32
|
+
assert_equal session.response.body, 'success'
|
33
|
+
assert_not_nil @user.reload.unique_session_id
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'session is logged out when another session is created' do
|
38
|
+
first_session = open_session
|
39
|
+
second_session = open_session
|
40
|
+
unique_session_id = nil
|
41
|
+
|
42
|
+
first_session.tap do |session|
|
43
|
+
sign_in(@user, session)
|
44
|
+
session.assert_redirected_to '/'
|
45
|
+
session.get widgets_path
|
46
|
+
session.assert_response(:success)
|
47
|
+
assert_equal session.response.body, 'success'
|
48
|
+
unique_session_id = @user.reload.unique_session_id
|
49
|
+
assert_not_nil unique_session_id
|
50
|
+
end
|
51
|
+
|
52
|
+
second_session.tap do |session|
|
53
|
+
sign_in(@user, session)
|
54
|
+
session.assert_redirected_to '/'
|
55
|
+
session.get widgets_path
|
56
|
+
session.assert_response(:success)
|
57
|
+
assert_equal session.response.body, 'success'
|
58
|
+
assert_not_equal unique_session_id, @user.reload.unique_session_id
|
59
|
+
end
|
60
|
+
|
61
|
+
first_session.tap do |session|
|
62
|
+
session.get widgets_path
|
63
|
+
session.assert_redirected_to new_user_session_path
|
64
|
+
assert_equal session.flash[:alert], I18n.t('devise.failure.session_limited')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module IntegrationHelpers
|
2
|
+
# login the user. This will exercise all the Warden Hooks
|
3
|
+
# @param user [User]
|
4
|
+
# @param session [ActionDispatch::Integration::Session]
|
5
|
+
# @return [void]
|
6
|
+
# @note accounts for differences in the integration test API between rails versions
|
7
|
+
def sign_in(user, session)
|
8
|
+
if Rails.gem_version > Gem::Version.new('5.0')
|
9
|
+
session.post new_user_session_path, params: {
|
10
|
+
user: {
|
11
|
+
email: user.email,
|
12
|
+
password: user.password
|
13
|
+
}
|
14
|
+
}
|
15
|
+
else
|
16
|
+
session.post new_user_session_path, {
|
17
|
+
user: {
|
18
|
+
email: user.email,
|
19
|
+
password: user.password
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# attempt to login the user with a bad password. This will exercise all the Warden Hooks
|
26
|
+
# @param user [User]
|
27
|
+
# @param session [ActionDispatch::Integration::Session]
|
28
|
+
# @return [void]
|
29
|
+
# @note accounts for differences in the integration test API between rails versions
|
30
|
+
def failed_sign_in(user, session)
|
31
|
+
if Rails.gem_version > Gem::Version.new('5.0')
|
32
|
+
session.post new_user_session_path, params: {
|
33
|
+
user: {
|
34
|
+
email: user.email,
|
35
|
+
password: 'bad-password'
|
36
|
+
}
|
37
|
+
}
|
38
|
+
else
|
39
|
+
session.post new_user_session_path, {
|
40
|
+
user: {
|
41
|
+
email: user.email,
|
42
|
+
password: 'bad-password'
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestCompatibility < ActiveSupport::TestCase
|
4
|
+
test 'can access ActiveRecord namespace' do
|
5
|
+
skip unless DEVISE_ORM == :active_record
|
6
|
+
assert_nothing_raised { User.new.some_method_calling_active_record }
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'can access Mongoid namespace' do
|
10
|
+
skip unless DEVISE_ORM == :mongoid
|
11
|
+
assert_nothing_raised { User.new.some_method_calling_mongoid }
|
12
|
+
end
|
13
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -5,9 +5,17 @@ ENV['RAILS_ENV'] ||= 'test'
|
|
5
5
|
require 'simplecov'
|
6
6
|
SimpleCov.start do
|
7
7
|
add_filter 'gemfiles'
|
8
|
+
add_filter 'test/dummy/db'
|
9
|
+
add_group 'ActiveRecord', 'active_record'
|
10
|
+
add_group 'Expirable', /(?<!password_)expirable/
|
11
|
+
add_group 'Mongoid', 'mongoid'
|
12
|
+
add_group 'Paranoid Verifiable', 'paranoid_verification'
|
13
|
+
add_group 'Password Archivable', /password_archivable|old_password/
|
14
|
+
add_group 'Password Expirable', /password_expirable|password_expired/
|
15
|
+
add_group 'Secure Validateable', 'secure_validatable'
|
16
|
+
add_group 'Security Questionable', 'security_question'
|
17
|
+
add_group 'Session Limitable', 'session_limitable'
|
8
18
|
add_group 'Tests', 'test'
|
9
|
-
add_group 'Password Archivable', 'password_archivable'
|
10
|
-
add_group 'Password Expirable', 'password_expirable'
|
11
19
|
end
|
12
20
|
|
13
21
|
if ENV['CI']
|
@@ -23,6 +31,7 @@ require 'rails/test_help'
|
|
23
31
|
require 'devise-security'
|
24
32
|
require 'database_cleaner'
|
25
33
|
require "orm/#{DEVISE_ORM}"
|
34
|
+
require 'support/integration_helpers'
|
26
35
|
|
27
36
|
class Minitest::Test
|
28
37
|
def before_setup
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestSessionLimitable < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test '#update_unique_session_id!(value) updates valid record' do
|
6
|
+
user = User.create! password: 'passWord1', password_confirmation: 'passWord1', email: 'bob@microsoft.com'
|
7
|
+
assert user.persisted?
|
8
|
+
assert_nil user.unique_session_id
|
9
|
+
user.update_unique_session_id!('unique_value')
|
10
|
+
user.reload
|
11
|
+
assert_equal user.unique_session_id, 'unique_value'
|
12
|
+
end
|
13
|
+
|
14
|
+
test '#update_unique_session_id!(value) updates invalid record atomically' do
|
15
|
+
user = User.create! password: 'passWord1', password_confirmation: 'passWord1', email: 'bob@microsoft.com'
|
16
|
+
assert user.persisted?
|
17
|
+
user.email = ''
|
18
|
+
assert user.invalid?
|
19
|
+
assert_nil user.unique_session_id
|
20
|
+
user.update_unique_session_id!('unique_value')
|
21
|
+
user.reload
|
22
|
+
assert_equal user.email, 'bob@microsoft.com'
|
23
|
+
assert_equal user.unique_session_id, 'unique_value'
|
24
|
+
end
|
25
|
+
|
26
|
+
test '#update_unique_session_id!(value) raises an exception on an unpersisted record' do
|
27
|
+
user = User.create
|
28
|
+
assert !user.persisted?
|
29
|
+
assert_raises(Devise::Models::Compatibility::NotPersistedError) { user.update_unique_session_id!('unique_value') }
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-security
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marco Scholl
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2019-
|
15
|
+
date: 2019-05-21 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
@@ -293,8 +293,8 @@ files:
|
|
293
293
|
- lib/devise-security/hooks/session_limitable.rb
|
294
294
|
- lib/devise-security/models/active_record/old_password.rb
|
295
295
|
- lib/devise-security/models/compatibility.rb
|
296
|
-
- lib/devise-security/models/compatibility/
|
297
|
-
- lib/devise-security/models/compatibility/
|
296
|
+
- lib/devise-security/models/compatibility/active_record_patch.rb
|
297
|
+
- lib/devise-security/models/compatibility/mongoid_patch.rb
|
298
298
|
- lib/devise-security/models/database_authenticatable_patch.rb
|
299
299
|
- lib/devise-security/models/expirable.rb
|
300
300
|
- lib/devise-security/models/mongoid/old_password.rb
|
@@ -324,11 +324,15 @@ files:
|
|
324
324
|
- lib/devise-security/version.rb
|
325
325
|
- lib/generators/devise_security/install_generator.rb
|
326
326
|
- lib/generators/templates/devise-security.rb
|
327
|
+
- test/controllers/test_captcha_controller.rb
|
328
|
+
- test/controllers/test_password_expired_controller.rb
|
329
|
+
- test/controllers/test_security_question_controller.rb
|
327
330
|
- test/dummy/Rakefile
|
328
331
|
- test/dummy/app/controllers/application_controller.rb
|
329
332
|
- test/dummy/app/controllers/captcha/sessions_controller.rb
|
330
333
|
- test/dummy/app/controllers/foos_controller.rb
|
331
334
|
- test/dummy/app/controllers/security_question/unlocks_controller.rb
|
335
|
+
- test/dummy/app/controllers/widgets_controller.rb
|
332
336
|
- test/dummy/app/models/.gitkeep
|
333
337
|
- test/dummy/app/models/application_record.rb
|
334
338
|
- test/dummy/app/models/application_user_record.rb
|
@@ -390,19 +394,20 @@ files:
|
|
390
394
|
- test/dummy/lib/shared_user_without_email.rb
|
391
395
|
- test/dummy/lib/shared_user_without_omniauth.rb
|
392
396
|
- test/dummy/lib/shared_verification_fields.rb
|
397
|
+
- test/integration/test_session_limitable_workflow.rb
|
393
398
|
- test/orm/active_record.rb
|
394
399
|
- test/orm/mongoid.rb
|
400
|
+
- test/support/integration_helpers.rb
|
395
401
|
- test/support/mongoid.yml
|
396
|
-
- test/
|
402
|
+
- test/test_compatibility.rb
|
397
403
|
- test/test_complexity_validator.rb
|
398
404
|
- test/test_helper.rb
|
399
405
|
- test/test_install_generator.rb
|
400
406
|
- test/test_paranoid_verification.rb
|
401
407
|
- test/test_password_archivable.rb
|
402
408
|
- test/test_password_expirable.rb
|
403
|
-
- test/test_password_expired_controller.rb
|
404
409
|
- test/test_secure_validatable.rb
|
405
|
-
- test/
|
410
|
+
- test/test_session_limitable.rb
|
406
411
|
homepage: https://github.com/devise-security/devise-security
|
407
412
|
licenses:
|
408
413
|
- MIT
|
@@ -428,11 +433,15 @@ signing_key:
|
|
428
433
|
specification_version: 4
|
429
434
|
summary: Security extension for devise
|
430
435
|
test_files:
|
436
|
+
- test/controllers/test_captcha_controller.rb
|
437
|
+
- test/controllers/test_password_expired_controller.rb
|
438
|
+
- test/controllers/test_security_question_controller.rb
|
431
439
|
- test/dummy/Rakefile
|
432
440
|
- test/dummy/app/controllers/application_controller.rb
|
433
441
|
- test/dummy/app/controllers/captcha/sessions_controller.rb
|
434
442
|
- test/dummy/app/controllers/foos_controller.rb
|
435
443
|
- test/dummy/app/controllers/security_question/unlocks_controller.rb
|
444
|
+
- test/dummy/app/controllers/widgets_controller.rb
|
436
445
|
- test/dummy/app/models/.gitkeep
|
437
446
|
- test/dummy/app/models/application_record.rb
|
438
447
|
- test/dummy/app/models/application_user_record.rb
|
@@ -494,16 +503,17 @@ test_files:
|
|
494
503
|
- test/dummy/lib/shared_user_without_email.rb
|
495
504
|
- test/dummy/lib/shared_user_without_omniauth.rb
|
496
505
|
- test/dummy/lib/shared_verification_fields.rb
|
506
|
+
- test/integration/test_session_limitable_workflow.rb
|
497
507
|
- test/orm/active_record.rb
|
498
508
|
- test/orm/mongoid.rb
|
509
|
+
- test/support/integration_helpers.rb
|
499
510
|
- test/support/mongoid.yml
|
500
|
-
- test/
|
511
|
+
- test/test_compatibility.rb
|
501
512
|
- test/test_complexity_validator.rb
|
502
513
|
- test/test_helper.rb
|
503
514
|
- test/test_install_generator.rb
|
504
515
|
- test/test_paranoid_verification.rb
|
505
516
|
- test/test_password_archivable.rb
|
506
517
|
- test/test_password_expirable.rb
|
507
|
-
- test/test_password_expired_controller.rb
|
508
518
|
- test/test_secure_validatable.rb
|
509
|
-
- test/
|
519
|
+
- test/test_session_limitable.rb
|