authenticate 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +14 -2
- data/Gemfile +2 -2
- data/Gemfile.lock +2 -3
- data/README.md +103 -30
- data/app/controllers/authenticate/authenticate_controller.rb +2 -0
- data/app/controllers/authenticate/passwords_controller.rb +1 -1
- data/app/controllers/authenticate/sessions_controller.rb +1 -1
- data/app/controllers/authenticate/users_controller.rb +1 -1
- data/app/views/passwords/new.html.erb +4 -0
- data/authenticate.gemspec +8 -10
- data/config/locales/authenticate.en.yml +9 -1
- data/gemfiles/rails42.gemfile +12 -0
- data/lib/authenticate/callbacks/authenticatable.rb +4 -1
- data/lib/authenticate/callbacks/brute_force.rb +2 -1
- data/lib/authenticate/callbacks/lifetimed.rb +2 -2
- data/lib/authenticate/callbacks/timeoutable.rb +1 -1
- data/lib/authenticate/callbacks/trackable.rb +1 -1
- data/lib/authenticate/controller.rb +12 -3
- data/lib/authenticate/debug.rb +8 -3
- data/lib/authenticate/engine.rb +3 -0
- data/lib/authenticate/lifecycle.rb +25 -16
- data/lib/authenticate/model/brute_force.rb +7 -3
- data/lib/authenticate/model/db_password.rb +12 -14
- data/lib/authenticate/model/email.rb +1 -1
- data/lib/authenticate/model/lifetimed.rb +7 -8
- data/lib/authenticate/model/password_reset.rb +12 -5
- data/lib/authenticate/model/timeoutable.rb +9 -12
- data/lib/authenticate/model/trackable.rb +5 -2
- data/lib/authenticate/model/username.rb +0 -8
- data/lib/authenticate/modules.rb +3 -2
- data/lib/authenticate/session.rb +7 -7
- data/lib/authenticate/version.rb +1 -1
- data/spec/dummy/config/initializers/authenticate.rb +3 -2
- data/spec/factories/users.rb +11 -1
- data/spec/model/db_password_spec.rb +33 -0
- data/spec/model/email_spec.rb +25 -0
- data/spec/model/lifetimed_spec.rb +35 -0
- data/spec/model/password_reset_spec.rb +81 -0
- data/spec/model/session_spec.rb +0 -6
- data/spec/model/timeoutable_spec.rb +20 -0
- data/spec/model/trackable_spec.rb +56 -0
- data/spec/spec_helper.rb +6 -0
- metadata +18 -13
@@ -42,16 +42,8 @@ module Authenticate
|
|
42
42
|
username = credentials[0]
|
43
43
|
find_by_username username
|
44
44
|
end
|
45
|
-
|
46
|
-
# def normalize_username(username)
|
47
|
-
# username.to_s.downcase.gsub(/\s+/, '')
|
48
|
-
# end
|
49
45
|
end
|
50
46
|
|
51
|
-
# def normalize_username
|
52
|
-
# self.username = self.class.normalize_username(username)
|
53
|
-
# end
|
54
|
-
|
55
47
|
end
|
56
48
|
|
57
49
|
end
|
data/lib/authenticate/modules.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Authenticate
|
2
2
|
module Modules
|
3
3
|
extend ActiveSupport::Concern
|
4
|
+
include Authenticate::Debug
|
4
5
|
|
5
6
|
# Module to help Authenticate's user model load Authenticate modules.
|
6
7
|
#
|
@@ -26,7 +27,7 @@ module Authenticate
|
|
26
27
|
def load_modules
|
27
28
|
constants = []
|
28
29
|
Authenticate.configuration.modules.each do |mod|
|
29
|
-
puts "load_modules about to load #{mod.to_s}"
|
30
|
+
# puts "load_modules about to load #{mod.to_s}"
|
30
31
|
require "authenticate/model/#{mod.to_s}" if mod.is_a?(Symbol)
|
31
32
|
mod = load_constant(mod) if mod.is_a?(Symbol)
|
32
33
|
constants << mod
|
@@ -70,7 +71,7 @@ module Authenticate
|
|
70
71
|
end
|
71
72
|
|
72
73
|
def message
|
73
|
-
"The following attribute(s) is (are) missing on your model: #{@attributes.join(", ")}"
|
74
|
+
"The following attribute(s) is (are) missing on your user model: #{@attributes.join(", ")}"
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
data/lib/authenticate/session.rb
CHANGED
@@ -11,7 +11,7 @@ module Authenticate
|
|
11
11
|
@request = request # trackable module accesses request
|
12
12
|
@cookies = cookies
|
13
13
|
@session_token = @cookies[cookie_name]
|
14
|
-
|
14
|
+
debug 'SESSION initialize: @session_token: ' + @session_token.inspect
|
15
15
|
end
|
16
16
|
|
17
17
|
# consecutive_failed_logins_limit
|
@@ -28,9 +28,9 @@ module Authenticate
|
|
28
28
|
#
|
29
29
|
# @return [User]
|
30
30
|
def login(user, &block)
|
31
|
-
|
31
|
+
debug 'session.login()'
|
32
32
|
@current_user = user
|
33
|
-
|
33
|
+
debug "session.login @current_user: #{@current_user.inspect}"
|
34
34
|
# todo extract token gen to two different strategies
|
35
35
|
@current_user.generate_session_token if user.present?
|
36
36
|
|
@@ -39,7 +39,7 @@ module Authenticate
|
|
39
39
|
Authenticate.lifecycle.run_callbacks(:after_authentication, @current_user, self, { event: :authentication })
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
debug "session.login after lifecycle callbacks, message: #{message}"
|
43
43
|
status = message.present? ? Failure.new(message) : Success.new
|
44
44
|
if status.success?
|
45
45
|
@current_user.save
|
@@ -58,7 +58,7 @@ module Authenticate
|
|
58
58
|
#
|
59
59
|
# @return [User]
|
60
60
|
def current_user
|
61
|
-
|
61
|
+
debug 'session.current_user'
|
62
62
|
if @session_token.present?
|
63
63
|
@current_user ||= load_user
|
64
64
|
end
|
@@ -69,7 +69,7 @@ module Authenticate
|
|
69
69
|
#
|
70
70
|
# @return [Boolean]
|
71
71
|
def authenticated?
|
72
|
-
|
72
|
+
debug 'session.authenticated?'
|
73
73
|
current_user.present?
|
74
74
|
end
|
75
75
|
|
@@ -109,7 +109,7 @@ module Authenticate
|
|
109
109
|
cookie_hash[:domain] = Authenticate.configuration.cookie_domain if Authenticate.configuration.cookie_domain
|
110
110
|
# @cookies.signed[cookie_name] = cookie_hash
|
111
111
|
@cookies[cookie_name] = cookie_hash
|
112
|
-
|
112
|
+
debug 'session.write_cookie WROTE COOKIE I HOPE. Cookie guts:' + @cookies[cookie_name].inspect
|
113
113
|
end
|
114
114
|
|
115
115
|
def cookie_name
|
data/lib/authenticate/version.rb
CHANGED
@@ -6,9 +6,10 @@ Authenticate.configure do |config|
|
|
6
6
|
# config.cookie_path = '/'
|
7
7
|
# config.secure_cookie = false # set to true in production https environments
|
8
8
|
# config.http_only = false # set to true if you can
|
9
|
-
|
10
|
-
|
9
|
+
config.timeout_in = 45.minutes
|
10
|
+
config.max_session_lifetime = 5.minutes
|
11
11
|
config.max_consecutive_bad_logins_allowed = 1
|
12
12
|
config.bad_login_lockout_period = 2.minutes
|
13
|
+
config.reset_password_within = 5.minutes
|
13
14
|
# config.authentication_strategy = :email
|
14
15
|
end
|
data/spec/factories/users.rb
CHANGED
@@ -7,7 +7,17 @@ FactoryGirl.define do
|
|
7
7
|
|
8
8
|
factory :user do
|
9
9
|
email
|
10
|
-
encrypted_password 'password'
|
10
|
+
# encrypted_password 'password'
|
11
|
+
password 'password'
|
12
|
+
|
13
|
+
trait :without_email do
|
14
|
+
email nil
|
15
|
+
end
|
16
|
+
|
17
|
+
trait :without_password do
|
18
|
+
password nil
|
19
|
+
encrypted_password nil
|
20
|
+
end
|
11
21
|
|
12
22
|
trait :with_session_token do
|
13
23
|
session_token 'this_is_a_big_fake_long_token'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/db_password'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::DbPassword do
|
6
|
+
|
7
|
+
it 'validates password' do
|
8
|
+
user = build(:user, :without_password)
|
9
|
+
user.save
|
10
|
+
expect(user.errors.count).to be(1)
|
11
|
+
expect(user.errors.messages[:password]).to eq(["can't be blank"])
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'matches a password' do
|
15
|
+
user = create(:user)
|
16
|
+
expect(user.password_match? 'password').to be_truthy
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'fails to match a bad password' do
|
20
|
+
user = create(:user)
|
21
|
+
expect(user.password_match? 'bad password').to be_falsey
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets a password' do
|
25
|
+
user = create(:user)
|
26
|
+
user.password = 'new_password'
|
27
|
+
user.save!
|
28
|
+
|
29
|
+
user = User.find(user.id)
|
30
|
+
expect(user.password_match? 'new_password').to be_truthy
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/email'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::Email do
|
6
|
+
|
7
|
+
it 'validates email' do
|
8
|
+
user = build(:user, :without_email)
|
9
|
+
user.save
|
10
|
+
expect(user.errors.count).to be(2)
|
11
|
+
expect(user.errors.messages[:email]).to include('is invalid')
|
12
|
+
expect(user.errors.messages[:email]).to include("can't be blank")
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'extracts credentials from params' do
|
16
|
+
params = {session:{email:'foo', password:'bar'}}
|
17
|
+
expect(User.credentials(params)).to match_array(['foo', 'bar'])
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'authenticates from credentials' do
|
21
|
+
user = create(:user)
|
22
|
+
expect(User.authenticate([user.email, user.password])).to eq(user)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/lifetimed'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::Lifetimed do
|
6
|
+
|
7
|
+
context '#max_session_lifetime_exceeded?' do
|
8
|
+
before {
|
9
|
+
Authenticate.configure do |config|
|
10
|
+
config.max_session_lifetime = 10.minutes
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
it 'passes fresh sessions' do
|
15
|
+
user = create(:user, current_sign_in_at: 1.minute.ago.utc)
|
16
|
+
expect(user).to_not be_max_session_lifetime_exceeded
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'detects timed out sessions' do
|
20
|
+
user = create(:user, current_sign_in_at: 5.hours.ago.utc)
|
21
|
+
expect(user).to be_max_session_lifetime_exceeded
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'max_session_lifetime param not set' do
|
25
|
+
it 'does not time out' do
|
26
|
+
user = create(:user, current_sign_in_at: 5.hours.ago.utc)
|
27
|
+
Authenticate.configure do |config|
|
28
|
+
config.max_session_lifetime = nil
|
29
|
+
end
|
30
|
+
expect(user).to_not be_max_session_lifetime_exceeded
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/password_reset'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::PasswordReset do
|
6
|
+
before(:all) {
|
7
|
+
Authenticate.configuration.reset_password_within = 5.minutes
|
8
|
+
}
|
9
|
+
context 'forgot_password!' do
|
10
|
+
subject { create(:user) }
|
11
|
+
before { subject.forgot_password! }
|
12
|
+
|
13
|
+
it 'generates a password reset token' do
|
14
|
+
expect(subject.password_reset_token).to_not be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sets password reset sent at' do
|
18
|
+
expect(subject.password_reset_sent_at).to_not be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
context '#reset_password_period_valid?' do
|
24
|
+
subject { create(:user) }
|
25
|
+
before(:each) {
|
26
|
+
Authenticate.configuration.reset_password_within = 5.minutes
|
27
|
+
}
|
28
|
+
|
29
|
+
it 'always true if reset_password_within config param is nil' do
|
30
|
+
subject.password_reset_sent_at = 10.days.ago
|
31
|
+
Authenticate.configuration.reset_password_within = nil
|
32
|
+
expect(subject.reset_password_period_valid?).to be_truthy
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'false if time exceeded' do
|
36
|
+
subject.password_reset_sent_at = 10.minutes.ago
|
37
|
+
expect(subject.reset_password_period_valid?).to be_falsey
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'true if time within limit' do
|
41
|
+
subject.password_reset_sent_at = 1.minutes.ago
|
42
|
+
expect(subject.reset_password_period_valid?).to be_truthy
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context '#update_password' do
|
47
|
+
subject { create(:user) }
|
48
|
+
before(:each) {
|
49
|
+
Authenticate.configuration.reset_password_within = 5.minutes
|
50
|
+
}
|
51
|
+
|
52
|
+
context 'within time time' do
|
53
|
+
before(:each) {
|
54
|
+
subject.password_reset_sent_at = 1.minutes.ago
|
55
|
+
}
|
56
|
+
|
57
|
+
it 'allows password update within time limit' do
|
58
|
+
expect(subject.update_password 'chongo').to be_truthy
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'clears password reset token' do
|
62
|
+
subject.update_password 'chongo'
|
63
|
+
expect(subject.password_reset_token).to be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'generates a new session token' do
|
67
|
+
token = subject.session_token
|
68
|
+
subject.update_password 'chongo'
|
69
|
+
expect(subject.session_token).to_not eq(token)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'stops password update after time limit' do
|
75
|
+
subject.password_reset_sent_at = 6.minutes.ago
|
76
|
+
expect(subject.update_password 'chongo').to be_falsey
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/spec/model/session_spec.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/timeoutable'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::Timeoutable do
|
6
|
+
before(:all) {
|
7
|
+
Authenticate.configuration.timeout_in = 45.minutes
|
8
|
+
}
|
9
|
+
subject { create(:user) }
|
10
|
+
|
11
|
+
it 'does not timeout while last_access_at is valid' do
|
12
|
+
subject.last_access_at = 10.minutes.ago
|
13
|
+
expect(subject.timedout?).to be_falsey
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'does timeout when last_access_at is stale' do
|
17
|
+
subject.last_access_at = 46.minutes.ago
|
18
|
+
expect(subject.timedout?).to be_truthy
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'authenticate/model/trackable'
|
3
|
+
|
4
|
+
|
5
|
+
describe Authenticate::Model::Trackable do
|
6
|
+
subject {create(:user)}
|
7
|
+
|
8
|
+
context '#last_sign_in_at' do
|
9
|
+
it 'sets to old current_sign_in_at if it is not nil' do
|
10
|
+
old_sign_in = 2.days.ago.utc
|
11
|
+
subject.current_sign_in_at = old_sign_in
|
12
|
+
subject.update_tracked_fields mock_request
|
13
|
+
expect(subject.last_sign_in_at).to eq(old_sign_in)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sets to current time if old current_sign_in_at is nil' do
|
17
|
+
subject.current_sign_in_at = nil
|
18
|
+
subject.update_tracked_fields mock_request
|
19
|
+
expect(subject.last_sign_in_at).to be_within(5.seconds).of(Time.now.utc)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context '#last_sign_in_ip' do
|
24
|
+
it 'sets to old current_sign_in_ip if it is not nil' do
|
25
|
+
old_ip = '222.222.222.222'
|
26
|
+
subject.current_sign_in_ip = old_ip
|
27
|
+
subject.update_tracked_fields mock_request
|
28
|
+
expect(subject.last_sign_in_ip).to eq(old_ip)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sets to current ip if old current_sign_in_ip is nil' do
|
32
|
+
subject.current_sign_in_ip = nil
|
33
|
+
subject.update_tracked_fields mock_request
|
34
|
+
expect(subject.last_sign_in_ip).to_not be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sets current_sign_in_at to now' do
|
39
|
+
subject.current_sign_in_at = nil
|
40
|
+
subject.update_tracked_fields mock_request
|
41
|
+
expect(subject.current_sign_in_at).to be_within(5.seconds).of(Time.now.utc)
|
42
|
+
end
|
43
|
+
|
44
|
+
context '#sign_in_count' do
|
45
|
+
it 'initializes a nil count' do
|
46
|
+
subject.sign_in_count = nil
|
47
|
+
subject.update_tracked_fields mock_request
|
48
|
+
expect(subject.sign_in_count).to eq(1)
|
49
|
+
end
|
50
|
+
it 'increments existing count' do
|
51
|
+
subject.sign_in_count = 4
|
52
|
+
subject.update_tracked_fields mock_request
|
53
|
+
expect(subject.sign_in_count).to eq(5)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -53,6 +53,12 @@ def restore_default_configuration
|
|
53
53
|
Authenticate.configure {}
|
54
54
|
end
|
55
55
|
|
56
|
+
def mock_request(params = {})
|
57
|
+
req = double("request")
|
58
|
+
allow(req).to receive(:params).and_return(params)
|
59
|
+
allow(req).to receive(:remote_ip).and_return('111.111.111.111')
|
60
|
+
req
|
61
|
+
end
|
56
62
|
|
57
63
|
|
58
64
|
# # This file was generated by the `rails generate rspec:install` command. Conventionally, all
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authenticate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Tomich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcrypt
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '5.1'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: factory_girl_rails
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
90
|
+
name: pry
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
93
|
- - ">="
|
@@ -101,7 +101,7 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
104
|
+
name: sqlite3
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - ">="
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
|
-
description:
|
117
|
+
description: Authentication for Rails applications
|
118
118
|
email:
|
119
119
|
- justin@tomich.org
|
120
120
|
executables: []
|
@@ -122,10 +122,12 @@ extensions: []
|
|
122
122
|
extra_rdoc_files:
|
123
123
|
- LICENSE
|
124
124
|
- README.md
|
125
|
+
- CHANGELOG.md
|
125
126
|
files:
|
126
127
|
- ".gitignore"
|
127
128
|
- ".rspec"
|
128
129
|
- ".ruby-version"
|
130
|
+
- ".travis.yml"
|
129
131
|
- CHANGELOG.md
|
130
132
|
- Gemfile
|
131
133
|
- Gemfile.lock
|
@@ -136,6 +138,7 @@ files:
|
|
136
138
|
- app/assets/images/authenticate/.keep
|
137
139
|
- app/assets/javascripts/authenticate/.keep
|
138
140
|
- app/assets/stylesheets/authenticate/.keep
|
141
|
+
- app/controllers/authenticate/authenticate_controller.rb
|
139
142
|
- app/controllers/authenticate/passwords_controller.rb
|
140
143
|
- app/controllers/authenticate/sessions_controller.rb
|
141
144
|
- app/controllers/authenticate/users_controller.rb
|
@@ -153,6 +156,7 @@ files:
|
|
153
156
|
- bin/rails
|
154
157
|
- config/locales/authenticate.en.yml
|
155
158
|
- config/routes.rb
|
159
|
+
- gemfiles/rails42.gemfile
|
156
160
|
- lib/authenticate.rb
|
157
161
|
- lib/authenticate/callbacks/authenticatable.rb
|
158
162
|
- lib/authenticate/callbacks/brute_force.rb
|
@@ -249,8 +253,14 @@ files:
|
|
249
253
|
- spec/dummy/public/favicon.ico
|
250
254
|
- spec/factories/users.rb
|
251
255
|
- spec/model/brute_force_spec.rb
|
256
|
+
- spec/model/db_password_spec.rb
|
257
|
+
- spec/model/email_spec.rb
|
258
|
+
- spec/model/lifetimed_spec.rb
|
259
|
+
- spec/model/password_reset_spec.rb
|
252
260
|
- spec/model/session_spec.rb
|
261
|
+
- spec/model/timeoutable_spec.rb
|
253
262
|
- spec/model/token_spec.rb
|
263
|
+
- spec/model/trackable_spec.rb
|
254
264
|
- spec/model/user_spec.rb
|
255
265
|
- spec/orm/active_record.rb
|
256
266
|
- spec/spec_helper.rb
|
@@ -278,10 +288,5 @@ rubyforge_project:
|
|
278
288
|
rubygems_version: 2.5.1
|
279
289
|
signing_key:
|
280
290
|
specification_version: 4
|
281
|
-
summary:
|
282
|
-
test_files:
|
283
|
-
- spec/configuration_spec.rb
|
284
|
-
- spec/model/brute_force_spec.rb
|
285
|
-
- spec/model/session_spec.rb
|
286
|
-
- spec/model/token_spec.rb
|
287
|
-
- spec/model/user_spec.rb
|
291
|
+
summary: Authentication for Rails applications
|
292
|
+
test_files: []
|