sorcery 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sorcery might be problematic. Click here for more details.
- data/Gemfile +1 -2
- data/LICENSE.txt +1 -1
- data/README.rdoc +27 -11
- data/Rakefile +2 -13
- data/VERSION +1 -1
- data/lib/sorcery.rb +4 -1
- data/lib/sorcery/controller.rb +13 -7
- data/lib/sorcery/controller/submodules/activity_logging.rb +45 -0
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +8 -69
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +7 -4
- data/lib/sorcery/controller/submodules/session_timeout.rb +4 -1
- data/lib/sorcery/crypto_providers/bcrypt.rb +1 -5
- data/lib/sorcery/model/submodules/activity_logging.rb +35 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +72 -0
- data/lib/sorcery/model/submodules/remember_me.rb +3 -1
- data/lib/sorcery/model/submodules/reset_password.rb +93 -0
- data/lib/sorcery/model/submodules/user_activation.rb +2 -0
- data/sorcery.gemspec +26 -14
- data/spec/rails3/app_root/app/controllers/application_controller.rb +2 -2
- data/spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
- data/spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
- data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/rails3/controller_activity_logging_spec.rb +84 -0
- data/spec/rails3/controller_brute_force_protection_spec.rb +24 -41
- data/spec/rails3/controller_http_basic_auth_spec.rb +10 -0
- data/spec/rails3/controller_session_timeout_spec.rb +1 -0
- data/spec/rails3/controller_spec.rb +3 -3
- data/spec/rails3/spec_helper.rb +39 -19
- data/spec/rails3/user_activity_logging_spec.rb +36 -0
- data/spec/rails3/user_brute_force_protection_spec.rb +76 -0
- data/spec/rails3/user_reset_password_spec.rb +198 -0
- metadata +34 -22
- data/features/support/env.rb +0 -13
- data/lib/sorcery/model/submodules/password_reset.rb +0 -64
- data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +0 -9
- data/spec/rails3/user_password_reset_spec.rb +0 -76
@@ -0,0 +1,35 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Model
|
3
|
+
module Submodules
|
4
|
+
module ActivityLogging
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
base.sorcery_config.class_eval do
|
8
|
+
attr_accessor :last_login_at_attribute_name, # last login attribute name.
|
9
|
+
:last_logout_at_attribute_name, # last logout attribute name.
|
10
|
+
:last_activity_at_attribute_name, # last activity attribute name.
|
11
|
+
:activity_timeout # how long since last activity is the user defined logged out?
|
12
|
+
end
|
13
|
+
|
14
|
+
base.sorcery_config.instance_eval do
|
15
|
+
@defaults.merge!(:@last_login_at_attribute_name => :last_login_at,
|
16
|
+
:@last_logout_at_attribute_name => :last_logout_at,
|
17
|
+
:@last_activity_at_attribute_name => :last_activity_at,
|
18
|
+
:@activity_timeout => 10.minutes)
|
19
|
+
reset!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
# get all users with last_activity within timeout
|
25
|
+
def logged_in_users
|
26
|
+
config = sorcery_config
|
27
|
+
where("#{config.last_activity_at_attribute_name} IS NOT NULL") \
|
28
|
+
.where("#{config.last_logout_at_attribute_name} IS NULL OR #{config.last_activity_at_attribute_name} > #{config.last_logout_at_attribute_name}") \
|
29
|
+
.where("#{config.last_activity_at_attribute_name} > ? ", config.activity_timeout.seconds.ago)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Model
|
3
|
+
module Submodules
|
4
|
+
module BruteForceProtection
|
5
|
+
def self.included(base)
|
6
|
+
base.sorcery_config.class_eval do
|
7
|
+
attr_accessor :failed_logins_count_attribute_name, # failed logins attribute name.
|
8
|
+
:lock_expires_at_attribute_name, # this field indicates whether user is banned and when it will be active again.
|
9
|
+
:consecutive_login_retries_amount_allowed, # how many failed logins allowed.
|
10
|
+
:login_lock_time_period # how long the user should be banned. in seconds. 0 for permanent.
|
11
|
+
end
|
12
|
+
|
13
|
+
base.sorcery_config.instance_eval do
|
14
|
+
@defaults.merge!(:@failed_logins_count_attribute_name => :failed_logins_count,
|
15
|
+
:@lock_expires_at_attribute_name => :lock_expires_at,
|
16
|
+
:@consecutive_login_retries_amount_allowed => 50,
|
17
|
+
:@login_lock_time_period => 3600)
|
18
|
+
reset!
|
19
|
+
end
|
20
|
+
|
21
|
+
base.class_eval do
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
base.sorcery_config.before_authenticate << :prevent_locked_user_login
|
26
|
+
base.extend(ClassMethods)
|
27
|
+
base.send(:include, InstanceMethods)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
protected
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
module InstanceMethods
|
36
|
+
def register_failed_login!
|
37
|
+
config = sorcery_config
|
38
|
+
self.increment(config.failed_logins_count_attribute_name)
|
39
|
+
save!
|
40
|
+
self.lock! if self.send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_allowed
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def lock!
|
46
|
+
config = sorcery_config
|
47
|
+
self.update_attributes!(config.lock_expires_at_attribute_name => Time.now.utc + config.login_lock_time_period)
|
48
|
+
end
|
49
|
+
|
50
|
+
def unlock!
|
51
|
+
config = sorcery_config
|
52
|
+
self.update_attributes!(config.lock_expires_at_attribute_name => nil,
|
53
|
+
config.failed_logins_count_attribute_name => 0)
|
54
|
+
end
|
55
|
+
|
56
|
+
def unlocked?
|
57
|
+
config = sorcery_config
|
58
|
+
self.send(config.lock_expires_at_attribute_name).nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def prevent_locked_user_login
|
62
|
+
config = sorcery_config
|
63
|
+
if !self.unlocked?
|
64
|
+
self.unlock! if self.send(config.lock_expires_at_attribute_name) <= Time.now.utc
|
65
|
+
end
|
66
|
+
unlocked?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -22,13 +22,15 @@ module Sorcery
|
|
22
22
|
end
|
23
23
|
|
24
24
|
module InstanceMethods
|
25
|
+
# You shouldn't really use this one - it's called by the controller's 'remember_me!' method.
|
25
26
|
def remember_me!
|
26
27
|
config = sorcery_config
|
27
28
|
self.send(:"#{config.remember_me_token_attribute_name}=", generate_random_code)
|
28
29
|
self.send(:"#{config.remember_me_token_expires_at_attribute_name}=", Time.now + config.remember_me_for)
|
29
30
|
self.save!(:validate => false)
|
30
31
|
end
|
31
|
-
|
32
|
+
|
33
|
+
# You shouldn't really use this one - it's called by the controller's 'forget_me!' method.
|
32
34
|
def forget_me!
|
33
35
|
config = sorcery_config
|
34
36
|
self.send(:"#{config.remember_me_token_attribute_name}=", nil)
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Model
|
3
|
+
module Submodules
|
4
|
+
# This submodule adds the ability to reset password via email confirmation.
|
5
|
+
module ResetPassword
|
6
|
+
def self.included(base)
|
7
|
+
base.sorcery_config.class_eval do
|
8
|
+
attr_accessor :reset_password_token_attribute_name, # reset password code attribute name.
|
9
|
+
:reset_password_token_expires_at_attribute_name, # expires at attribute name.
|
10
|
+
:reset_password_email_sent_at_attribute_name, # when was email sent, used for hammering protection.
|
11
|
+
:reset_password_mailer, # mailer class. Needed.
|
12
|
+
:reset_password_email_method_name, # reset password email method on your mailer class.
|
13
|
+
:reset_password_expiration_period, # how many seconds before the reset request expires. nil for never expires.
|
14
|
+
:reset_password_time_between_emails # hammering protection, how long to wait before allowing another email to be sent.
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
base.sorcery_config.instance_eval do
|
19
|
+
@defaults.merge!(:@reset_password_token_attribute_name => :reset_password_token,
|
20
|
+
:@reset_password_token_expires_at_attribute_name => :reset_password_token_expires_at,
|
21
|
+
:@reset_password_email_sent_at_attribute_name => :reset_password_email_sent_at,
|
22
|
+
:@reset_password_mailer => nil,
|
23
|
+
:@reset_password_email_method_name => :reset_password_email,
|
24
|
+
:@reset_password_expiration_period => nil,
|
25
|
+
:@reset_password_time_between_emails => 5.minutes )
|
26
|
+
|
27
|
+
reset!
|
28
|
+
end
|
29
|
+
|
30
|
+
base.sorcery_config.after_config << :validate_mailer_defined
|
31
|
+
|
32
|
+
base.extend(ClassMethods)
|
33
|
+
base.send(:include, InstanceMethods)
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
|
38
|
+
def load_from_reset_password_token(token)
|
39
|
+
return nil if token.blank?
|
40
|
+
user = where("#{@sorcery_config.reset_password_token_attribute_name} = ?", token).first
|
41
|
+
if !user.blank? && !@sorcery_config.reset_password_expiration_period.nil?
|
42
|
+
return user.reset_password_token_valid? ? user : nil
|
43
|
+
end
|
44
|
+
user
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def validate_mailer_defined
|
50
|
+
msg = "To use reset_password submodule, you must define a mailer (config.reset_password_mailer = YourMailerClass)."
|
51
|
+
raise ArgumentError, msg if @sorcery_config.reset_password_mailer == nil
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
module InstanceMethods
|
57
|
+
# generates a reset code with expiration and sends an email to the user.
|
58
|
+
def deliver_reset_password_instructions!
|
59
|
+
config = sorcery_config
|
60
|
+
# hammering protection
|
61
|
+
return if config.reset_password_time_between_emails && self.send(config.reset_password_email_sent_at_attribute_name) && self.send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.ago.utc
|
62
|
+
self.send(:"#{config.reset_password_token_attribute_name}=", generate_random_code)
|
63
|
+
self.send(:"#{config.reset_password_token_expires_at_attribute_name}=", Time.now.utc + config.reset_password_expiration_period) if config.reset_password_expiration_period
|
64
|
+
self.send(:"#{config.reset_password_email_sent_at_attribute_name}=", Time.now.utc)
|
65
|
+
self.class.transaction do
|
66
|
+
self.save!(:validate => false)
|
67
|
+
generic_send_email(:reset_password_email_method_name, :reset_password_mailer)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def reset_password!(params)
|
72
|
+
clear_reset_password_token
|
73
|
+
update_attributes(params)
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset_password_token_valid?
|
77
|
+
config = sorcery_config
|
78
|
+
config.reset_password_expiration_period ? Time.now.utc < self.send(config.reset_password_token_expires_at_attribute_name) : true
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def clear_reset_password_token
|
84
|
+
config = sorcery_config
|
85
|
+
self.send(:"#{config.reset_password_token_attribute_name}=", nil)
|
86
|
+
self.send(:"#{config.reset_password_token_expires_at_attribute_name}=", nil) if config.reset_password_expiration_period
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -40,6 +40,8 @@ module Sorcery
|
|
40
40
|
end
|
41
41
|
|
42
42
|
module ClassMethods
|
43
|
+
protected
|
44
|
+
|
43
45
|
def validate_mailer_defined
|
44
46
|
msg = "To use user_activation submodule, you must define a mailer (config.user_activation_mailer = YourMailerClass)."
|
45
47
|
raise ArgumentError, msg if @sorcery_config.user_activation_mailer == nil
|
data/sorcery.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sorcery}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Noam Ben Ari"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-19}
|
13
13
|
s.description = %q{Provides common authentication needs such as signing in/out, activating by email and resetting password.}
|
14
14
|
s.email = %q{nbenari@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
|
|
25
25
|
"README.rdoc",
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
|
-
"features/support/env.rb",
|
29
28
|
"lib/sorcery.rb",
|
30
29
|
"lib/sorcery/controller.rb",
|
30
|
+
"lib/sorcery/controller/submodules/activity_logging.rb",
|
31
31
|
"lib/sorcery/controller/submodules/brute_force_protection.rb",
|
32
32
|
"lib/sorcery/controller/submodules/http_basic_auth.rb",
|
33
33
|
"lib/sorcery/controller/submodules/remember_me.rb",
|
@@ -40,8 +40,10 @@ Gem::Specification.new do |s|
|
|
40
40
|
"lib/sorcery/crypto_providers/sha512.rb",
|
41
41
|
"lib/sorcery/engine.rb",
|
42
42
|
"lib/sorcery/model.rb",
|
43
|
-
"lib/sorcery/model/submodules/
|
43
|
+
"lib/sorcery/model/submodules/activity_logging.rb",
|
44
|
+
"lib/sorcery/model/submodules/brute_force_protection.rb",
|
44
45
|
"lib/sorcery/model/submodules/remember_me.rb",
|
46
|
+
"lib/sorcery/model/submodules/reset_password.rb",
|
45
47
|
"lib/sorcery/model/submodules/user_activation.rb",
|
46
48
|
"sorcery.gemspec",
|
47
49
|
"spec/Gemfile",
|
@@ -82,9 +84,11 @@ Gem::Specification.new do |s|
|
|
82
84
|
"spec/rails3/app_root/config/locales/en.yml",
|
83
85
|
"spec/rails3/app_root/config/routes.rb",
|
84
86
|
"spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb",
|
87
|
+
"spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb",
|
88
|
+
"spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb",
|
85
89
|
"spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb",
|
86
|
-
"spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb",
|
87
90
|
"spec/rails3/app_root/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb",
|
91
|
+
"spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb",
|
88
92
|
"spec/rails3/app_root/db/schema.rb",
|
89
93
|
"spec/rails3/app_root/db/seeds.rb",
|
90
94
|
"spec/rails3/app_root/lib/tasks/.gitkeep",
|
@@ -108,6 +112,7 @@ Gem::Specification.new do |s|
|
|
108
112
|
"spec/rails3/app_root/test/test_helper.rb",
|
109
113
|
"spec/rails3/app_root/test/unit/user_test.rb",
|
110
114
|
"spec/rails3/app_root/vendor/plugins/.gitkeep",
|
115
|
+
"spec/rails3/controller_activity_logging_spec.rb",
|
111
116
|
"spec/rails3/controller_brute_force_protection_spec.rb",
|
112
117
|
"spec/rails3/controller_http_basic_auth_spec.rb",
|
113
118
|
"spec/rails3/controller_remember_me_spec.rb",
|
@@ -115,8 +120,10 @@ Gem::Specification.new do |s|
|
|
115
120
|
"spec/rails3/controller_spec.rb",
|
116
121
|
"spec/rails3/spec_helper.rb",
|
117
122
|
"spec/rails3/user_activation_spec.rb",
|
118
|
-
"spec/rails3/
|
123
|
+
"spec/rails3/user_activity_logging_spec.rb",
|
124
|
+
"spec/rails3/user_brute_force_protection_spec.rb",
|
119
125
|
"spec/rails3/user_remember_me_spec.rb",
|
126
|
+
"spec/rails3/user_reset_password_spec.rb",
|
120
127
|
"spec/rails3/user_spec.rb",
|
121
128
|
"spec/sorcery_crypto_providers_spec.rb",
|
122
129
|
"spec/spec_helper.rb"
|
@@ -145,14 +152,17 @@ Gem::Specification.new do |s|
|
|
145
152
|
"spec/rails3/app_root/config/initializers/session_store.rb",
|
146
153
|
"spec/rails3/app_root/config/routes.rb",
|
147
154
|
"spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb",
|
155
|
+
"spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb",
|
156
|
+
"spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb",
|
148
157
|
"spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb",
|
149
|
-
"spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb",
|
150
158
|
"spec/rails3/app_root/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb",
|
159
|
+
"spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb",
|
151
160
|
"spec/rails3/app_root/db/schema.rb",
|
152
161
|
"spec/rails3/app_root/db/seeds.rb",
|
153
162
|
"spec/rails3/app_root/test/performance/browsing_test.rb",
|
154
163
|
"spec/rails3/app_root/test/test_helper.rb",
|
155
164
|
"spec/rails3/app_root/test/unit/user_test.rb",
|
165
|
+
"spec/rails3/controller_activity_logging_spec.rb",
|
156
166
|
"spec/rails3/controller_brute_force_protection_spec.rb",
|
157
167
|
"spec/rails3/controller_http_basic_auth_spec.rb",
|
158
168
|
"spec/rails3/controller_remember_me_spec.rb",
|
@@ -160,8 +170,10 @@ Gem::Specification.new do |s|
|
|
160
170
|
"spec/rails3/controller_spec.rb",
|
161
171
|
"spec/rails3/spec_helper.rb",
|
162
172
|
"spec/rails3/user_activation_spec.rb",
|
163
|
-
"spec/rails3/
|
173
|
+
"spec/rails3/user_activity_logging_spec.rb",
|
174
|
+
"spec/rails3/user_brute_force_protection_spec.rb",
|
164
175
|
"spec/rails3/user_remember_me_spec.rb",
|
176
|
+
"spec/rails3/user_reset_password_spec.rb",
|
165
177
|
"spec/rails3/user_spec.rb",
|
166
178
|
"spec/sorcery_crypto_providers_spec.rb",
|
167
179
|
"spec/spec_helper.rb"
|
@@ -171,39 +183,39 @@ Gem::Specification.new do |s|
|
|
171
183
|
s.specification_version = 3
|
172
184
|
|
173
185
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
174
|
-
s.add_development_dependency(%q<rails>, ["
|
186
|
+
s.add_development_dependency(%q<rails>, [">= 3.0.0"])
|
175
187
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
176
188
|
s.add_development_dependency(%q<rspec-rails>, [">= 0"])
|
177
189
|
s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
|
178
190
|
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
179
191
|
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
180
|
-
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
181
192
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
182
193
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
183
194
|
s.add_development_dependency(%q<simplecov>, [">= 0.3.8"])
|
195
|
+
s.add_runtime_dependency(%q<bcrypt-ruby>, ["~> 2.1.4"])
|
184
196
|
else
|
185
|
-
s.add_dependency(%q<rails>, ["
|
197
|
+
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
186
198
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
187
199
|
s.add_dependency(%q<rspec-rails>, [">= 0"])
|
188
200
|
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
189
201
|
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
190
202
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
191
|
-
s.add_dependency(%q<cucumber>, [">= 0"])
|
192
203
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
193
204
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
194
205
|
s.add_dependency(%q<simplecov>, [">= 0.3.8"])
|
206
|
+
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.4"])
|
195
207
|
end
|
196
208
|
else
|
197
|
-
s.add_dependency(%q<rails>, ["
|
209
|
+
s.add_dependency(%q<rails>, [">= 3.0.0"])
|
198
210
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
199
211
|
s.add_dependency(%q<rspec-rails>, [">= 0"])
|
200
212
|
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
201
213
|
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
202
214
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
203
|
-
s.add_dependency(%q<cucumber>, [">= 0"])
|
204
215
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
205
216
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
206
217
|
s.add_dependency(%q<simplecov>, [">= 0.3.8"])
|
218
|
+
s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.4"])
|
207
219
|
end
|
208
220
|
end
|
209
221
|
|
@@ -2,8 +2,8 @@ class ApplicationController < ActionController::Base
|
|
2
2
|
protect_from_forgery
|
3
3
|
|
4
4
|
#before_filter :validate_session, :only => [:test_should_be_logged_in] if defined?(:validate_session)
|
5
|
-
before_filter :
|
6
|
-
before_filter :
|
5
|
+
before_filter :require_login_from_http_basic, :only => [:test_http_basic_auth]
|
6
|
+
before_filter :require_login, :only => [:test_logout, :test_should_be_logged_in, :some_action]
|
7
7
|
|
8
8
|
def index
|
9
9
|
render :text => ""
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddActivityLoggingToUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :users, :last_login_at, :datetime, :default => nil
|
4
|
+
add_column :users, :last_logout_at, :datetime, :default => nil
|
5
|
+
add_column :users, :last_activity_at, :datetime, :default => nil
|
6
|
+
|
7
|
+
add_index :users, [:last_logout_at, :last_activity_at]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
remove_index :users, [:last_logout_at, :last_activity_at]
|
12
|
+
|
13
|
+
remove_column :users, :last_activity_at
|
14
|
+
remove_column :users, :last_logout_at
|
15
|
+
remove_column :users, :last_login_at
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddBruteForceProtectionToUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :users, :failed_logins_count, :integer, :default => 0
|
4
|
+
add_column :users, :lock_expires_at, :datetime, :default => nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_column :users, :lock_expires_at
|
9
|
+
remove_column :users, :failed_logins_count
|
10
|
+
end
|
11
|
+
end
|
data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddResetPasswordToUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :users, :reset_password_token, :string, :default => nil
|
4
|
+
add_column :users, :reset_password_token_expires_at, :datetime, :default => nil
|
5
|
+
add_column :users, :reset_password_email_sent_at, :datetime, :default => nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
remove_column :users, :reset_password_email_sent_at
|
10
|
+
remove_column :users, :reset_password_token_expires_at
|
11
|
+
remove_column :users, :reset_password_token
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ApplicationController do
|
4
|
+
before(:all) do
|
5
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:all) do
|
9
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
|
10
|
+
end
|
11
|
+
|
12
|
+
# ----------------- ACTIVITY LOGGING -----------------------
|
13
|
+
describe ApplicationController, "with activity logging features" do
|
14
|
+
before(:all) do
|
15
|
+
plugin_model_configure([:activity_logging])
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
create_new_user
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:each) do
|
23
|
+
User.delete_all
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should respond to 'logged_in_users'" do
|
27
|
+
subject.should respond_to(:logged_in_users)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "'logged_in_users' should be empty when no users are logged in" do
|
31
|
+
subject.logged_in_users.size.should == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should log login time on login" do
|
35
|
+
now = Time.now.utc
|
36
|
+
login_user
|
37
|
+
@user.last_login_at.should_not be_nil
|
38
|
+
@user.last_login_at.to_s(:db).should >= now.to_s(:db)
|
39
|
+
@user.last_login_at.to_s(:db).should <= (now+2).to_s(:db)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should log logout time on logout" do
|
43
|
+
login_user
|
44
|
+
now = Time.now.utc
|
45
|
+
logout_user
|
46
|
+
User.first.last_logout_at.should_not be_nil
|
47
|
+
User.first.last_logout_at.to_s(:db).should >= now.to_s(:db)
|
48
|
+
User.first.last_logout_at.to_s(:db).should <= (now+2).to_s(:db)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should log last activity time when logged in" do
|
52
|
+
login_user
|
53
|
+
now = Time.now.utc
|
54
|
+
get :some_action
|
55
|
+
User.first.last_activity_at.to_s(:db).should >= now.to_s(:db)
|
56
|
+
User.first.last_activity_at.to_s(:db).should <= (now+2).to_s(:db)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "'logged_in_users' should hold the user object when 1 user is logged in" do
|
60
|
+
login_user
|
61
|
+
get :some_action
|
62
|
+
subject.logged_in_users.size.should == 1
|
63
|
+
subject.logged_in_users[0].should == @user
|
64
|
+
end
|
65
|
+
|
66
|
+
it "'logged_in_users' should show all logged_in_users, whether they have logged out before or not." do
|
67
|
+
user1 = create_new_user({:username => 'gizmo1', :email => "bla1@bla.com", :password => 'secret1'})
|
68
|
+
login_user(user1)
|
69
|
+
get :some_action
|
70
|
+
clear_user_without_logout
|
71
|
+
user2 = create_new_user({:username => 'gizmo2', :email => "bla2@bla.com", :password => 'secret2'})
|
72
|
+
login_user(user2)
|
73
|
+
get :some_action
|
74
|
+
clear_user_without_logout
|
75
|
+
user3 = create_new_user({:username => 'gizmo3', :email => "bla3@bla.com", :password => 'secret3'})
|
76
|
+
login_user(user3)
|
77
|
+
get :some_action
|
78
|
+
subject.logged_in_users.size.should == 3
|
79
|
+
subject.logged_in_users[0].should == user1
|
80
|
+
subject.logged_in_users[1].should == user2
|
81
|
+
subject.logged_in_users[2].should == user3
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|