sorcery 0.8.6 → 0.9.1

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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +75 -14
  4. data/CHANGELOG.md +32 -1
  5. data/Gemfile +1 -0
  6. data/README.md +138 -86
  7. data/gemfiles/active_record-rails40.gemfile +7 -0
  8. data/gemfiles/active_record-rails41.gemfile +3 -2
  9. data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
  10. data/gemfiles/mongo_mapper-rails41.gemfile +2 -1
  11. data/gemfiles/mongoid-rails40.gemfile +9 -0
  12. data/gemfiles/mongoid-rails41.gemfile +3 -5
  13. data/gemfiles/mongoid3-rails32.gemfile +9 -0
  14. data/lib/generators/sorcery/USAGE +1 -1
  15. data/lib/generators/sorcery/install_generator.rb +19 -5
  16. data/lib/generators/sorcery/templates/initializer.rb +36 -10
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
  18. data/lib/generators/sorcery/templates/migration/core.rb +2 -2
  19. data/lib/generators/sorcery/templates/migration/external.rb +3 -1
  20. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  21. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  22. data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
  23. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
  24. data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
  25. data/lib/sorcery/controller/config.rb +65 -0
  26. data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
  27. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
  28. data/lib/sorcery/controller/submodules/external.rb +9 -29
  29. data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
  30. data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
  31. data/lib/sorcery/controller.rb +5 -64
  32. data/lib/sorcery/model/config.rb +96 -0
  33. data/lib/sorcery/model/submodules/activity_logging.rb +29 -36
  34. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -37
  35. data/lib/sorcery/model/submodules/external.rb +53 -9
  36. data/lib/sorcery/model/submodules/remember_me.rb +12 -31
  37. data/lib/sorcery/model/submodules/reset_password.rb +21 -39
  38. data/lib/sorcery/model/submodules/user_activation.rb +21 -63
  39. data/lib/sorcery/model/temporary_token.rb +4 -4
  40. data/lib/sorcery/model.rb +47 -175
  41. data/lib/sorcery/providers/base.rb +11 -0
  42. data/lib/sorcery/providers/facebook.rb +16 -5
  43. data/lib/sorcery/providers/github.rb +11 -2
  44. data/lib/sorcery/providers/google.rb +1 -1
  45. data/lib/sorcery/providers/heroku.rb +57 -0
  46. data/lib/sorcery/providers/jira.rb +77 -0
  47. data/lib/sorcery/providers/linkedin.rb +1 -1
  48. data/lib/sorcery/providers/liveid.rb +1 -1
  49. data/lib/sorcery/providers/salesforce.rb +50 -0
  50. data/lib/sorcery/providers/twitter.rb +1 -1
  51. data/lib/sorcery/providers/vk.rb +6 -4
  52. data/lib/sorcery/providers/xing.rb +2 -2
  53. data/lib/sorcery/test_helpers/internal.rb +7 -3
  54. data/lib/sorcery/test_helpers/rails/controller.rb +5 -1
  55. data/lib/sorcery/version.rb +3 -0
  56. data/lib/sorcery.rb +75 -43
  57. data/sorcery.gemspec +6 -2
  58. data/spec/active_record/user_activity_logging_spec.rb +9 -0
  59. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  60. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  61. data/spec/{active_record → controllers}/controller_http_basic_auth_spec.rb +14 -11
  62. data/spec/{active_record → controllers}/controller_oauth2_spec.rb +151 -64
  63. data/spec/{active_record → controllers}/controller_oauth_spec.rb +94 -70
  64. data/spec/{active_record → controllers}/controller_remember_me_spec.rb +32 -12
  65. data/spec/{active_record → controllers}/controller_session_timeout_spec.rb +15 -5
  66. data/spec/{shared_examples/controller_shared_examples.rb → controllers/controller_spec.rb} +34 -19
  67. data/spec/{datamapper → data_mapper}/user_activation_spec.rb +1 -1
  68. data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
  69. data/spec/{datamapper → data_mapper}/user_brute_force_protection_spec.rb +1 -1
  70. data/spec/{datamapper → data_mapper}/user_oauth_spec.rb +1 -1
  71. data/spec/{datamapper → data_mapper}/user_remember_me_spec.rb +1 -1
  72. data/spec/{datamapper → data_mapper}/user_reset_password_spec.rb +1 -1
  73. data/spec/{datamapper → data_mapper}/user_spec.rb +1 -1
  74. data/spec/mongoid/user_spec.rb +13 -0
  75. data/spec/orm/active_record.rb +12 -0
  76. data/spec/orm/{datamapper.rb → data_mapper.rb} +16 -2
  77. data/spec/orm/mongo_mapper.rb +0 -1
  78. data/spec/orm/mongoid.rb +4 -0
  79. data/spec/rails_app/app/controllers/sorcery_controller.rb +62 -1
  80. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  81. data/spec/rails_app/config/routes.rb +9 -0
  82. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  83. data/spec/shared_examples/user_activation_shared_examples.rb +7 -7
  84. data/spec/shared_examples/user_activity_logging_shared_examples.rb +73 -5
  85. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +127 -9
  86. data/spec/shared_examples/user_oauth_shared_examples.rb +3 -6
  87. data/spec/shared_examples/user_remember_me_shared_examples.rb +6 -3
  88. data/spec/shared_examples/user_reset_password_shared_examples.rb +10 -10
  89. data/spec/shared_examples/user_shared_examples.rb +146 -46
  90. data/spec/spec_helper.rb +7 -22
  91. metadata +36 -57
  92. data/Gemfile.rails4 +0 -22
  93. data/VERSION +0 -1
  94. data/lib/sorcery/model/adapters/active_record.rb +0 -54
  95. data/lib/sorcery/model/adapters/datamapper.rb +0 -123
  96. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -60
  97. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  98. data/lib/sorcery/test_helpers/rails.rb +0 -7
  99. data/spec/active_record/controller_activity_logging_spec.rb +0 -29
  100. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -158
  101. data/spec/active_record/controller_spec.rb +0 -8
  102. data/spec/active_record/integration_spec.rb +0 -23
  103. data/spec/datamapper/controller_activity_logging_spec.rb +0 -17
  104. data/spec/datamapper/controller_spec.rb +0 -8
  105. data/spec/datamapper/user_activity_logging_spec.rb +0 -9
  106. data/spec/mongo_mapper/controller_spec.rb +0 -8
  107. data/spec/mongoid/controller_activity_logging_spec.rb +0 -16
  108. data/spec/mongoid/controller_spec.rb +0 -8
  109. data/spec/rails_app/public/404.html +0 -26
  110. data/spec/rails_app/public/422.html +0 -26
  111. data/spec/rails_app/public/500.html +0 -26
  112. data/spec/rails_app/public/favicon.ico +0 -0
  113. data/spec/rails_app/public/images/rails.png +0 -0
  114. data/spec/rails_app/public/javascripts/application.js +0 -2
  115. data/spec/rails_app/public/javascripts/controls.js +0 -965
  116. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  117. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  118. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  119. data/spec/rails_app/public/javascripts/rails.js +0 -175
  120. data/spec/rails_app/public/robots.txt +0 -5
  121. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  122. data/spec/shared_examples/controller_activity_logging_shared_examples.rb +0 -125
  123. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -52
  124. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -62
  125. /data/spec/rails_app/app/{datamapper → data_mapper}/authentication.rb +0 -0
  126. /data/spec/rails_app/app/{datamapper → data_mapper}/user.rb +0 -0
@@ -1,7 +1,7 @@
1
1
  module Sorcery
2
2
  module TestHelpers
3
3
  module Rails
4
- module Controller
4
+ module Controller
5
5
  def login_user(user = nil, test_context = {})
6
6
  user ||= @user
7
7
  @controller.send(:auto_login, user)
@@ -11,6 +11,10 @@ module Sorcery
11
11
  def logout_user
12
12
  @controller.send(:logout)
13
13
  end
14
+
15
+ def logged_in?
16
+ @controller.send(:logged_in?)
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -0,0 +1,3 @@
1
+ module Sorcery
2
+ VERSION = "0.9.1"
3
+ end
data/lib/sorcery.rb CHANGED
@@ -1,78 +1,110 @@
1
+ require 'sorcery/version'
2
+
1
3
  module Sorcery
2
- autoload :Model, 'sorcery/model'
4
+
5
+ require 'sorcery/model'
6
+
7
+ module Adapters
8
+ require 'sorcery/adapters/base_adapter'
9
+ end
10
+
3
11
  module Model
4
- autoload :TemporaryToken, 'sorcery/model/temporary_token'
5
- module Adapters
6
- autoload :ActiveRecord, 'sorcery/model/adapters/active_record'
7
- autoload :Mongoid, 'sorcery/model/adapters/mongoid'
8
- autoload :MongoMapper, 'sorcery/model/adapters/mongo_mapper'
9
- autoload :DataMapper, 'sorcery/model/adapters/datamapper'
10
- end
12
+ require 'sorcery/model/temporary_token'
13
+ require 'sorcery/model/config'
14
+
15
+
11
16
  module Submodules
12
- autoload :UserActivation, 'sorcery/model/submodules/user_activation'
13
- autoload :ResetPassword, 'sorcery/model/submodules/reset_password'
14
- autoload :RememberMe, 'sorcery/model/submodules/remember_me'
15
- autoload :ActivityLogging, 'sorcery/model/submodules/activity_logging'
16
- autoload :BruteForceProtection, 'sorcery/model/submodules/brute_force_protection'
17
- autoload :External, 'sorcery/model/submodules/external'
17
+ require 'sorcery/model/submodules/user_activation'
18
+ require 'sorcery/model/submodules/reset_password'
19
+ require 'sorcery/model/submodules/remember_me'
20
+ require 'sorcery/model/submodules/activity_logging'
21
+ require 'sorcery/model/submodules/brute_force_protection'
22
+ require 'sorcery/model/submodules/external'
18
23
  end
19
24
  end
20
- autoload :Controller, 'sorcery/controller'
25
+
26
+ require 'sorcery/controller'
27
+
21
28
  module Controller
29
+ autoload :Config, 'sorcery/controller/config'
22
30
  module Submodules
23
- autoload :RememberMe, 'sorcery/controller/submodules/remember_me'
24
- autoload :SessionTimeout, 'sorcery/controller/submodules/session_timeout'
25
- autoload :BruteForceProtection, 'sorcery/controller/submodules/brute_force_protection'
26
- autoload :HttpBasicAuth, 'sorcery/controller/submodules/http_basic_auth'
27
- autoload :ActivityLogging, 'sorcery/controller/submodules/activity_logging'
28
- autoload :External, 'sorcery/controller/submodules/external'
31
+ require 'sorcery/controller/submodules/remember_me'
32
+ require 'sorcery/controller/submodules/session_timeout'
33
+ require 'sorcery/controller/submodules/brute_force_protection'
34
+ require 'sorcery/controller/submodules/http_basic_auth'
35
+ require 'sorcery/controller/submodules/activity_logging'
36
+ require 'sorcery/controller/submodules/external'
29
37
  end
30
38
  end
39
+
31
40
  module Protocols
32
- autoload :Oauth, 'sorcery/protocols/oauth'
33
- autoload :Oauth2, 'sorcery/protocols/oauth2'
41
+ require 'sorcery/protocols/oauth'
42
+ require 'sorcery/protocols/oauth2'
34
43
  end
44
+
35
45
  module CryptoProviders
36
- autoload :Common, 'sorcery/crypto_providers/common'
37
- autoload :AES256, 'sorcery/crypto_providers/aes256'
38
- autoload :BCrypt, 'sorcery/crypto_providers/bcrypt'
39
- autoload :MD5, 'sorcery/crypto_providers/md5'
40
- autoload :SHA1, 'sorcery/crypto_providers/sha1'
41
- autoload :SHA256, 'sorcery/crypto_providers/sha256'
42
- autoload :SHA512, 'sorcery/crypto_providers/sha512'
46
+ require 'sorcery/crypto_providers/common'
47
+ require 'sorcery/crypto_providers/aes256'
48
+ require 'sorcery/crypto_providers/bcrypt'
49
+ require 'sorcery/crypto_providers/md5'
50
+ require 'sorcery/crypto_providers/sha1'
51
+ require 'sorcery/crypto_providers/sha256'
52
+ require 'sorcery/crypto_providers/sha512'
43
53
  end
54
+
44
55
  module TestHelpers
45
- autoload :Internal, 'sorcery/test_helpers/internal'
46
- module Internal
47
- autoload :Rails, 'sorcery/test_helpers/internal/rails'
48
- end
49
- autoload :Rails, 'sorcery/test_helpers/rails'
56
+ require 'sorcery/test_helpers/internal'
57
+
50
58
  module Rails
51
- autoload :Controller, 'sorcery/test_helpers/rails/controller'
52
- autoload :Integration, 'sorcery/test_helpers/rails/integration'
59
+ require 'sorcery/test_helpers/rails/controller'
60
+ require 'sorcery/test_helpers/rails/integration'
61
+ end
62
+
63
+ module Internal
64
+ require 'sorcery/test_helpers/internal/rails'
53
65
  end
54
66
 
55
67
  end
56
68
 
69
+ require 'sorcery/adapters/base_adapter'
70
+
57
71
  if defined?(ActiveRecord)
72
+ require 'sorcery/adapters/active_record_adapter'
58
73
  ActiveRecord::Base.extend Sorcery::Model
59
- ActiveRecord::Base.send :include, Sorcery::Model::Adapters::ActiveRecord
74
+
75
+ ActiveRecord::Base.send :define_method, :sorcery_adapter do
76
+ @sorcery_adapter ||= Sorcery::Adapters::ActiveRecordAdapter.new(self)
77
+ end
78
+
79
+ ActiveRecord::Base.send :define_singleton_method, :sorcery_adapter do
80
+ Sorcery::Adapters::ActiveRecordAdapter.from(self)
81
+ end
60
82
  end
61
83
 
62
84
  if defined?(Mongoid)
85
+ require 'sorcery/adapters/mongoid_adapter'
63
86
  Mongoid::Document::ClassMethods.send :include, Sorcery::Model
64
- Mongoid::Document::ClassMethods.send :include, Sorcery::Model::Adapters::Mongoid::ClassMethods
65
- Mongoid::Document.send :include, Sorcery::Model::Adapters::Mongoid::InstanceMethods
87
+
88
+ Mongoid::Document.send :define_method, :sorcery_adapter do
89
+ @sorcery_adapter ||= Sorcery::Adapters::MongoidAdapter.new(self)
90
+ end
91
+
92
+ Mongoid::Document::ClassMethods.send :define_method, :sorcery_adapter do
93
+ Sorcery::Adapters::MongoidAdapter.from(self)
94
+ end
66
95
  end
67
96
 
68
97
  if defined?(MongoMapper)
69
- MongoMapper::Document.send(:plugin, Sorcery::Model::Adapters::MongoMapper)
98
+ require 'sorcery/adapters/mongo_mapper_adapter'
99
+ MongoMapper::Document.send(:plugin, Sorcery::Adapters::MongoMapperAdapter::Wrapper)
70
100
  end
71
101
 
72
102
  if defined?(DataMapper)
103
+ require 'sorcery/adapters/data_mapper_adapter'
73
104
  DataMapper::Model.append_extensions(Sorcery::Model)
74
- DataMapper::Model.append_inclusions(Sorcery::Model::Adapters::DataMapper)
105
+
106
+ DataMapper::Model.append_inclusions(Sorcery::Adapters::DataMapperAdapter::Wrapper)
75
107
  end
76
108
 
77
- require 'sorcery/engine' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
109
+ require 'sorcery/engine' if defined?(Rails)
78
110
  end
data/sorcery.gemspec CHANGED
@@ -1,6 +1,10 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'sorcery/version'
4
+
1
5
  Gem::Specification.new do |s|
2
6
  s.name = "sorcery"
3
- s.version = "0.8.6"
7
+ s.version = Sorcery::VERSION
4
8
  s.authors = ["Noam Ben Ari", "Kir Shatrov", "Grzegorz Witek"]
5
9
  s.email = "nbenari@gmail.com"
6
10
  s.description = "Provides common authentication needs such as signing in/out, activating by email and resetting password."
@@ -15,7 +19,7 @@ Gem::Specification.new do |s|
15
19
  s.required_ruby_version = '>= 1.9.3'
16
20
 
17
21
  s.add_dependency "oauth", "~> 0.4", ">= 0.4.4"
18
- s.add_dependency "oauth2", ">= 0.8.0", "< 1.0.0"
22
+ s.add_dependency "oauth2", ">= 0.8.0"
19
23
  s.add_dependency "bcrypt", "~> 3.1"
20
24
 
21
25
  s.add_development_dependency "abstract", ">= 1.0.0"
@@ -3,6 +3,15 @@ require 'shared_examples/user_activity_logging_shared_examples'
3
3
 
4
4
  describe User, "with activity logging submodule", :active_record => true do
5
5
 
6
+ before(:all) do
7
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
8
+ User.reset_column_information
9
+ end
10
+
11
+ after(:all) do
12
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
13
+ end
14
+
6
15
  it_behaves_like "rails_3_activity_logging_model"
7
16
 
8
17
  end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ # require 'shared_examples/controller_activity_logging_shared_examples'
4
+
5
+ describe SorceryController do
6
+ after(:all) do
7
+ sorcery_controller_property_set(:register_login_time, true)
8
+ sorcery_controller_property_set(:register_logout_time, true)
9
+ sorcery_controller_property_set(:register_last_activity_time, true)
10
+ # sorcery_controller_property_set(:last_login_from_ip_address_name, true)
11
+ end
12
+
13
+ # ----------------- ACTIVITY LOGGING -----------------------
14
+ context "with activity logging features" do
15
+
16
+ let(:adapter) { double('sorcery_adapter') }
17
+ let(:user) { double('user', id: 42, sorcery_adapter: adapter) }
18
+
19
+ before(:all) do
20
+ sorcery_reload!([:activity_logging])
21
+ end
22
+
23
+ specify { expect(subject).to respond_to(:current_users) }
24
+
25
+ before(:each) do
26
+ allow(user).to receive(:username)
27
+ allow(user).to receive_message_chain(:sorcery_config, :username_attribute_names, :first) { :username }
28
+ allow(User.sorcery_config).to receive(:last_login_at_attribute_name) { :last_login_at }
29
+ allow(User.sorcery_config).to receive(:last_login_from_ip_address_name) { :last_login_from_ip_address }
30
+
31
+ sorcery_controller_property_set(:register_login_time, false)
32
+ sorcery_controller_property_set(:register_last_ip_address, false)
33
+ sorcery_controller_property_set(:register_last_activity_time, false)
34
+ end
35
+
36
+ it "'current_users' should proxy to User.current_users" do
37
+ expect(User).to receive(:current_users).with(no_args)
38
+
39
+ subject.current_users
40
+ end
41
+
42
+
43
+ it "logs login time on login" do
44
+ now = Time.now.in_time_zone
45
+ Timecop.freeze(now)
46
+
47
+ sorcery_controller_property_set(:register_login_time, true)
48
+ expect(user).to receive(:set_last_login_at).with(be_within(0.1).of(now))
49
+ login_user(user)
50
+
51
+ Timecop.return
52
+ end
53
+
54
+ it "logs logout time on logout" do
55
+ login_user(user)
56
+ now = Time.now.in_time_zone
57
+ Timecop.freeze(now)
58
+ expect(user).to receive(:set_last_logout_at).with(be_within(0.1).of(now))
59
+
60
+ logout_user
61
+
62
+ Timecop.return
63
+ end
64
+
65
+ it "logs last activity time when logged in" do
66
+ sorcery_controller_property_set(:register_last_activity_time, true)
67
+
68
+ login_user(user)
69
+ now = Time.now.in_time_zone
70
+ Timecop.freeze(now)
71
+ expect(user).to receive(:set_last_activity_at).with(be_within(0.1).of(now))
72
+
73
+ get :some_action
74
+
75
+ Timecop.return
76
+ end
77
+
78
+ it "logs last IP address when logged in" do
79
+ sorcery_controller_property_set(:register_last_ip_address, true)
80
+ expect(user).to receive(:set_last_ip_addess).with('0.0.0.0')
81
+
82
+ login_user(user)
83
+ end
84
+
85
+ it "updates nothing but activity fields" do
86
+ pending 'Move to model'
87
+ original_user_name = User.last.username
88
+ login_user(user)
89
+ get :some_action_making_a_non_persisted_change_to_the_user
90
+
91
+ expect(User.last.username).to eq original_user_name
92
+ end
93
+
94
+ it "does not register login time if configured so" do
95
+ sorcery_controller_property_set(:register_login_time, false)
96
+
97
+ expect(user).to receive(:set_last_login_at).never
98
+ login_user(user)
99
+ end
100
+
101
+ it "does not register logout time if configured so" do
102
+ sorcery_controller_property_set(:register_logout_time, false)
103
+ login_user(user)
104
+
105
+ expect(user).to receive(:set_last_logout_at).never
106
+ logout_user
107
+ end
108
+
109
+ it "does not register last activity time if configured so" do
110
+ sorcery_controller_property_set(:register_last_activity_time, false)
111
+
112
+ expect(user).to receive(:set_last_activity_at).never
113
+ login_user(user)
114
+ end
115
+
116
+ it "does not register last IP address if configured so" do
117
+ sorcery_controller_property_set(:register_last_ip_address, false)
118
+ expect(user).to receive(:set_last_ip_addess).never
119
+
120
+ login_user(user)
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe SorceryController do
4
+
5
+ let(:user) { double('user', id: 42, email: 'bla@bla.com') }
6
+
7
+ def request_test_login
8
+ get :test_login, email: 'bla@bla.com', password: 'blabla'
9
+ end
10
+
11
+ # ----------------- SESSION TIMEOUT -----------------------
12
+ describe "brute force protection features" do
13
+
14
+ before(:all) do
15
+ sorcery_reload!([:brute_force_protection])
16
+ end
17
+
18
+ after(:each) do
19
+ Sorcery::Controller::Config.reset!
20
+ sorcery_controller_property_set(:user_class, User)
21
+ Timecop.return
22
+ end
23
+
24
+ it "counts login retries" do
25
+ allow(User).to receive(:authenticate)
26
+ allow(User.sorcery_adapter).to receive(:find_by_credentials).with(['bla@bla.com', 'blabla']).and_return(user)
27
+
28
+ expect(user).to receive(:register_failed_login!).exactly(3).times
29
+
30
+ 3.times { request_test_login }
31
+ end
32
+
33
+ it "resets the counter on a good login" do
34
+ # dirty hack for rails 4
35
+ allow(@controller).to receive(:register_last_activity_time_to_db)
36
+
37
+ allow(User).to receive(:authenticate).and_return(user)
38
+ expect(user).to receive_message_chain(:sorcery_adapter, :update_attribute).with(:failed_logins_count, 0)
39
+
40
+ get :test_login, email: 'bla@bla.com', password: 'secret'
41
+ end
42
+ end
43
+ end
@@ -1,10 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe SorceryController, :active_record => true do
3
+ describe SorceryController do
4
4
 
5
- let!(:user) { create_new_user }
5
+ let(:user) { double("user", id: 42, email: 'bla@bla.com') }
6
6
 
7
- # ----------------- HTTP BASIC AUTH -----------------------
8
7
  describe "with http basic auth features" do
9
8
  before(:all) do
10
9
  sorcery_reload!([:http_basic_auth])
@@ -19,22 +18,24 @@ describe SorceryController, :active_record => true do
19
18
  it "requests basic authentication when before_filter is used" do
20
19
  get :test_http_basic_auth
21
20
 
22
- expect(response.code).to eq "401"
21
+ expect(response.status).to eq 401
23
22
  end
24
23
 
25
24
  it "authenticates from http basic if credentials are sent" do
26
25
  # dirty hack for rails 4
27
26
  allow(subject).to receive(:register_last_activity_time_to_db)
28
27
 
29
- @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{user.email}:secret")
30
- get :test_http_basic_auth, nil, :http_authentication_used => true
28
+ @request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64::encode64("#{user.email}:secret")}"
29
+ expect(User).to receive('authenticate').with('bla@bla.com', 'secret').and_return(user)
30
+ get :test_http_basic_auth, nil, http_authentication_used: true
31
31
 
32
32
  expect(response).to be_a_success
33
33
  end
34
34
 
35
35
  it "fails authentication if credentials are wrong" do
36
- @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{user.email}:wrong!")
37
- get :test_http_basic_auth, nil, :http_authentication_used => true
36
+ @request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64::encode64("#{user.email}:wrong!")}"
37
+ expect(User).to receive('authenticate').with('bla@bla.com', 'wrong!').and_return(nil)
38
+ get :test_http_basic_auth, nil, http_authentication_used: true
38
39
 
39
40
  expect(response).to redirect_to root_url
40
41
  end
@@ -56,10 +57,12 @@ describe SorceryController, :active_record => true do
56
57
  # dirty hack for rails 4
57
58
  allow(controller).to receive(:register_last_activity_time_to_db)
58
59
 
59
- @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{user.email}:secret")
60
- get :test_http_basic_auth, nil, :http_authentication_used => true
60
+ @request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64::encode64("#{user.email}:secret")}"
61
+ expect(User).to receive('authenticate').with('bla@bla.com', 'secret').and_return(user)
61
62
 
62
- expect(session[:user_id]).to be User.find_by_email(user.email).id
63
+ get :test_http_basic_auth, nil, http_authentication_used: true
64
+
65
+ expect(session[:user_id]).to eq "42"
63
66
  end
64
67
  end
65
68
  end