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.

Files changed (36) hide show
  1. data/Gemfile +1 -2
  2. data/LICENSE.txt +1 -1
  3. data/README.rdoc +27 -11
  4. data/Rakefile +2 -13
  5. data/VERSION +1 -1
  6. data/lib/sorcery.rb +4 -1
  7. data/lib/sorcery/controller.rb +13 -7
  8. data/lib/sorcery/controller/submodules/activity_logging.rb +45 -0
  9. data/lib/sorcery/controller/submodules/brute_force_protection.rb +8 -69
  10. data/lib/sorcery/controller/submodules/http_basic_auth.rb +7 -4
  11. data/lib/sorcery/controller/submodules/session_timeout.rb +4 -1
  12. data/lib/sorcery/crypto_providers/bcrypt.rb +1 -5
  13. data/lib/sorcery/model/submodules/activity_logging.rb +35 -0
  14. data/lib/sorcery/model/submodules/brute_force_protection.rb +72 -0
  15. data/lib/sorcery/model/submodules/remember_me.rb +3 -1
  16. data/lib/sorcery/model/submodules/reset_password.rb +93 -0
  17. data/lib/sorcery/model/submodules/user_activation.rb +2 -0
  18. data/sorcery.gemspec +26 -14
  19. data/spec/rails3/app_root/app/controllers/application_controller.rb +2 -2
  20. data/spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  21. data/spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  22. data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  23. data/spec/rails3/controller_activity_logging_spec.rb +84 -0
  24. data/spec/rails3/controller_brute_force_protection_spec.rb +24 -41
  25. data/spec/rails3/controller_http_basic_auth_spec.rb +10 -0
  26. data/spec/rails3/controller_session_timeout_spec.rb +1 -0
  27. data/spec/rails3/controller_spec.rb +3 -3
  28. data/spec/rails3/spec_helper.rb +39 -19
  29. data/spec/rails3/user_activity_logging_spec.rb +36 -0
  30. data/spec/rails3/user_brute_force_protection_spec.rb +76 -0
  31. data/spec/rails3/user_reset_password_spec.rb +198 -0
  32. metadata +34 -22
  33. data/features/support/env.rb +0 -13
  34. data/lib/sorcery/model/submodules/password_reset.rb +0 -64
  35. data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +0 -9
  36. 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.3"
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-05}
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/password_reset.rb",
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/user_password_reset_spec.rb",
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/user_password_reset_spec.rb",
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>, ["= 3.0.3"])
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>, ["= 3.0.3"])
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>, ["= 3.0.3"])
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 :require_user_login_from_http, :only => [:test_http_basic_auth]
6
- before_filter :require_user_login, :only => [:test_logout, :test_should_be_logged_in, :some_action]
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
@@ -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