sorcery 0.8.6 → 0.9.0

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +75 -14
  4. data/CHANGELOG.md +23 -1
  5. data/Gemfile +1 -0
  6. data/README.md +137 -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 +34 -9
  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.rb +75 -43
  21. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  22. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  23. data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
  24. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
  25. data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
  26. data/lib/sorcery/controller.rb +5 -64
  27. data/lib/sorcery/controller/config.rb +65 -0
  28. data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
  29. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
  30. data/lib/sorcery/controller/submodules/external.rb +8 -28
  31. data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
  32. data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
  33. data/lib/sorcery/model.rb +43 -175
  34. data/lib/sorcery/model/config.rb +96 -0
  35. data/lib/sorcery/model/submodules/activity_logging.rb +29 -36
  36. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -37
  37. data/lib/sorcery/model/submodules/external.rb +53 -9
  38. data/lib/sorcery/model/submodules/remember_me.rb +12 -31
  39. data/lib/sorcery/model/submodules/reset_password.rb +21 -39
  40. data/lib/sorcery/model/submodules/user_activation.rb +21 -63
  41. data/lib/sorcery/model/temporary_token.rb +4 -4
  42. data/lib/sorcery/providers/base.rb +11 -0
  43. data/lib/sorcery/providers/facebook.rb +1 -1
  44. data/lib/sorcery/providers/github.rb +1 -1
  45. data/lib/sorcery/providers/google.rb +1 -1
  46. data/lib/sorcery/providers/heroku.rb +57 -0
  47. data/lib/sorcery/providers/jira.rb +77 -0
  48. data/lib/sorcery/providers/linkedin.rb +1 -1
  49. data/lib/sorcery/providers/liveid.rb +1 -1
  50. data/lib/sorcery/providers/salesforce.rb +50 -0
  51. data/lib/sorcery/providers/twitter.rb +1 -1
  52. data/lib/sorcery/providers/vk.rb +6 -4
  53. data/lib/sorcery/providers/xing.rb +1 -1
  54. data/lib/sorcery/test_helpers/internal.rb +7 -3
  55. data/lib/sorcery/test_helpers/rails/controller.rb +5 -1
  56. data/lib/sorcery/version.rb +3 -0
  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 +128 -56
  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/{datamapper → data_mapper}/authentication.rb +0 -0
  81. data/spec/rails_app/app/{datamapper → data_mapper}/user.rb +0 -0
  82. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  83. data/spec/rails_app/config/routes.rb +9 -0
  84. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  85. data/spec/shared_examples/user_activation_shared_examples.rb +7 -7
  86. data/spec/shared_examples/user_activity_logging_shared_examples.rb +73 -5
  87. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +127 -9
  88. data/spec/shared_examples/user_oauth_shared_examples.rb +3 -6
  89. data/spec/shared_examples/user_remember_me_shared_examples.rb +6 -3
  90. data/spec/shared_examples/user_reset_password_shared_examples.rb +10 -10
  91. data/spec/shared_examples/user_shared_examples.rb +117 -30
  92. data/spec/spec_helper.rb +7 -22
  93. metadata +36 -58
  94. data/Gemfile.rails4 +0 -22
  95. data/VERSION +0 -1
  96. data/lib/sorcery/model/adapters/active_record.rb +0 -54
  97. data/lib/sorcery/model/adapters/datamapper.rb +0 -123
  98. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -60
  99. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  100. data/lib/sorcery/test_helpers/rails.rb +0 -7
  101. data/spec/active_record/controller_activity_logging_spec.rb +0 -29
  102. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -158
  103. data/spec/active_record/controller_spec.rb +0 -8
  104. data/spec/active_record/integration_spec.rb +0 -23
  105. data/spec/datamapper/controller_activity_logging_spec.rb +0 -17
  106. data/spec/datamapper/controller_spec.rb +0 -8
  107. data/spec/datamapper/user_activity_logging_spec.rb +0 -9
  108. data/spec/mongo_mapper/controller_spec.rb +0 -8
  109. data/spec/mongoid/controller_activity_logging_spec.rb +0 -16
  110. data/spec/mongoid/controller_spec.rb +0 -8
  111. data/spec/rails_app/public/404.html +0 -26
  112. data/spec/rails_app/public/422.html +0 -26
  113. data/spec/rails_app/public/500.html +0 -26
  114. data/spec/rails_app/public/favicon.ico +0 -0
  115. data/spec/rails_app/public/images/rails.png +0 -0
  116. data/spec/rails_app/public/javascripts/application.js +0 -2
  117. data/spec/rails_app/public/javascripts/controls.js +0 -965
  118. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  119. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  120. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  121. data/spec/rails_app/public/javascripts/rails.js +0 -175
  122. data/spec/rails_app/public/robots.txt +0 -5
  123. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  124. data/spec/shared_examples/controller_activity_logging_shared_examples.rb +0 -125
  125. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -52
  126. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -62
@@ -1,38 +1,156 @@
1
1
  shared_examples_for "rails_3_brute_force_protection_model" do
2
+ let(:user) { create_new_user }
3
+ before(:each) do
4
+ User.sorcery_adapter.delete_all
5
+ end
6
+
7
+
2
8
  context "loaded plugin configuration" do
3
9
 
4
10
  let(:config) { User.sorcery_config }
5
- let(:user) { create_new_user }
6
-
11
+
7
12
  before(:all) do
8
13
  sorcery_reload!([:brute_force_protection])
9
14
  end
10
-
15
+
11
16
  after(:each) do
12
17
  User.sorcery_config.reset!
13
18
  end
14
-
19
+
15
20
  specify { expect(user).to respond_to(:failed_logins_count) }
16
21
  specify { expect(user).to respond_to(:lock_expires_at) }
17
-
22
+
18
23
  it "enables configuration option 'failed_logins_count_attribute_name'" do
19
24
  sorcery_model_property_set(:failed_logins_count_attribute_name, :my_count)
20
25
  expect(config.failed_logins_count_attribute_name).to eq :my_count
21
26
  end
22
-
27
+
23
28
  it "enables configuration option 'lock_expires_at_attribute_name'" do
24
29
  sorcery_model_property_set(:lock_expires_at_attribute_name, :expires)
25
30
  expect(config.lock_expires_at_attribute_name).to eq :expires
26
31
  end
27
-
32
+
28
33
  it "enables configuration option 'consecutive_login_retries_amount_allowed'" do
29
34
  sorcery_model_property_set(:consecutive_login_retries_amount_limit, 34)
30
35
  expect(config.consecutive_login_retries_amount_limit).to eq 34
31
36
  end
32
-
37
+
33
38
  it "enables configuration option 'login_lock_time_period'" do
34
39
  sorcery_model_property_set(:login_lock_time_period, 2.hours)
35
40
  expect(config.login_lock_time_period).to eq 2.hours
36
41
  end
42
+
43
+ describe "#locked?" do
44
+ it "is locked" do
45
+ user.send("#{config.lock_expires_at_attribute_name}=", Time.now + 5.days)
46
+ expect(user).to be_locked
47
+ end
48
+
49
+ it "isn't locked" do
50
+ user.send("#{config.lock_expires_at_attribute_name}=", nil)
51
+ expect(user).not_to be_locked
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#register_failed_login!" do
57
+ it "locks user when number of retries reached the limit" do
58
+ expect(user.lock_expires_at).to be_nil
59
+
60
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 1)
61
+ user.register_failed_login!
62
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
63
+
64
+ expect(lock_expires_at).not_to be_nil
65
+ end
66
+
67
+ context "unlock_token_mailer_disabled is true" do
68
+ it "does not automatically send unlock email" do
69
+ sorcery_model_property_set(:unlock_token_mailer_disabled, true)
70
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
71
+ sorcery_model_property_set(:login_lock_time_period, 0)
72
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
73
+
74
+ 3.times { user.register_failed_login! }
75
+
76
+ expect(ActionMailer::Base.deliveries.size).to eq 0
77
+
78
+ end
79
+ end
80
+
81
+ context "unlock_token_mailer_disabled is false" do
82
+ before do
83
+ sorcery_model_property_set(:unlock_token_mailer_disabled, false)
84
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
85
+ sorcery_model_property_set(:login_lock_time_period, 0)
86
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
87
+ end
88
+
89
+ it "does not automatically send unlock email" do
90
+ 3.times { user.register_failed_login! }
91
+
92
+ expect(ActionMailer::Base.deliveries.size).to eq 1
93
+ end
94
+
95
+ it "generates unlock token before mail is sent" do
96
+ 3.times { user.register_failed_login! }
97
+
98
+ expect(ActionMailer::Base.deliveries.last.body.to_s.match(user.unlock_token)).not_to be_nil
99
+ end
100
+ end
101
+ end
102
+
103
+ context ".authenticate" do
104
+
105
+ it "unlocks after lock time period passes" do
106
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
107
+ sorcery_model_property_set(:login_lock_time_period, 0.2)
108
+ 2.times { user.register_failed_login! }
109
+
110
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
111
+ expect(lock_expires_at).not_to be_nil
112
+
113
+ Timecop.travel(Time.now.in_time_zone + 0.3)
114
+ User.authenticate('bla@bla.com', 'secret')
115
+
116
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
117
+ expect(lock_expires_at).to be_nil
118
+ Timecop.return
119
+ end
120
+
121
+ it "doest not unlock if time period is 0 (permanent lock)" do
122
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
123
+ sorcery_model_property_set(:login_lock_time_period, 0)
124
+
125
+ 2.times { user.register_failed_login! }
126
+
127
+ unlock_date = user.lock_expires_at
128
+ Timecop.travel(Time.now.in_time_zone + 1)
129
+
130
+ user.register_failed_login!
131
+
132
+ expect(user.lock_expires_at.to_s).to eq unlock_date.to_s
133
+ Timecop.return
134
+ end
135
+
136
+ end
137
+
138
+ describe "#unlock!" do
139
+ it "unlocks after entering unlock token" do
140
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
141
+ sorcery_model_property_set(:login_lock_time_period, 0)
142
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
143
+ 3.times { user.register_failed_login! }
144
+
145
+ expect(user.unlock_token).not_to be_nil
146
+
147
+ token = user.unlock_token
148
+ user = User.load_from_unlock_token(token)
149
+
150
+ expect(user).not_to be_nil
151
+
152
+ user.unlock!
153
+ expect(User.load_from_unlock_token(user.unlock_token)).to be_nil
154
+ end
37
155
  end
38
- end
156
+ end
@@ -6,12 +6,9 @@ shared_examples_for "rails_3_oauth_model" do
6
6
  describe "loaded plugin configuration" do
7
7
 
8
8
  before(:all) do
9
- if defined?(DataMapper) && User.ancestors.include?(DataMapper::Resource)
10
- Authentication.all.destroy
11
- else
12
- Authentication.delete_all
13
- end
14
- User.delete_all
9
+ Authentication.sorcery_adapter.delete_all
10
+ User.sorcery_adapter.delete_all
11
+
15
12
  sorcery_reload!([:external])
16
13
  sorcery_controller_property_set(:external_providers, [:twitter])
17
14
  sorcery_model_property_set(:authentications_class, Authentication)
@@ -35,12 +35,15 @@ shared_examples_for "rails_3_remember_me_model" do
35
35
  expect(user.remember_me_token).not_to be_nil
36
36
  end
37
37
 
38
- # FIXME: assert on line 37 sometimes fails by a second
39
38
  it "sets an expiration based on 'remember_me_for' attribute" do
40
39
  sorcery_model_property_set(:remember_me_for, 2 * 60 * 60 * 24)
41
- user.remember_me!
42
40
 
43
- expect(user.remember_me_token_expires_at.utc.to_s).to eq (Time.now.in_time_zone + 2 * 60 * 60 * 24).utc.to_s
41
+ ts = Time.now.in_time_zone
42
+ Timecop.freeze(ts) do
43
+ user.remember_me!
44
+ end
45
+
46
+ expect(user.remember_me_token_expires_at.utc.to_s).to eq (ts + 2 * 60 * 60 * 24).utc.to_s
44
47
  end
45
48
 
46
49
  it "deletes the token and expiration on 'forget_me!'" do
@@ -82,7 +82,7 @@ shared_examples_for "rails_3_reset_password_model" do
82
82
  end
83
83
 
84
84
  before(:each) do
85
- User.delete_all
85
+ User.sorcery_adapter.delete_all
86
86
  user
87
87
  end
88
88
 
@@ -91,29 +91,29 @@ shared_examples_for "rails_3_reset_password_model" do
91
91
  end
92
92
 
93
93
  it "load_from_reset_password_token returns user when token is found" do
94
- user.deliver_reset_password_instructions!
95
- updated_user = defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource) ? User.find(user.id) : user
94
+ user.generate_reset_password_token!
95
+ updated_user = User.sorcery_adapter.find(user.id)
96
96
 
97
97
  expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
98
98
  end
99
99
 
100
100
  it "load_from_reset_password_token does NOT return user when token is NOT found" do
101
- user.deliver_reset_password_instructions!
101
+ user.generate_reset_password_token!
102
102
 
103
103
  expect(User.load_from_reset_password_token "a").to be_nil
104
104
  end
105
105
 
106
106
  it "load_from_reset_password_token returns user when token is found and not expired" do
107
107
  sorcery_model_property_set(:reset_password_expiration_period, 500)
108
- user.deliver_reset_password_instructions!
109
- updated_user = defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource) ? User.find(user.id) : user
108
+ user.generate_reset_password_token!
109
+ updated_user = User.sorcery_adapter.find(user.id)
110
110
 
111
111
  expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
112
112
  end
113
113
 
114
114
  it "load_from_reset_password_token does NOT return user when token is found and expired" do
115
115
  sorcery_model_property_set(:reset_password_expiration_period, 0.1)
116
- user.deliver_reset_password_instructions!
116
+ user.generate_reset_password_token!
117
117
  Timecop.travel(Time.now.in_time_zone+0.5)
118
118
 
119
119
  expect(User.load_from_reset_password_token user.reset_password_token).to be_nil
@@ -121,8 +121,8 @@ shared_examples_for "rails_3_reset_password_model" do
121
121
 
122
122
  it "load_from_reset_password_token is always valid if expiration period is nil" do
123
123
  sorcery_model_property_set(:reset_password_expiration_period, nil)
124
- user.deliver_reset_password_instructions!
125
- updated_user = defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource) ? User.find(user.id) : user
124
+ user.generate_reset_password_token!
125
+ updated_user = User.sorcery_adapter.find(user.id)
126
126
 
127
127
  expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
128
128
  end
@@ -156,7 +156,7 @@ shared_examples_for "rails_3_reset_password_model" do
156
156
 
157
157
  expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
158
158
  end
159
-
159
+
160
160
  it "calls send_reset_password_email! on reset" do
161
161
  expect(user).to receive(:send_reset_password_email!).once
162
162
 
@@ -69,12 +69,16 @@ shared_examples_for "rails_3_core_model" do
69
69
 
70
70
  expect(User.sorcery_config.stretches).to eq stretches
71
71
  end
72
+
73
+ it 'respond to username=' do
74
+ expect(User.new).to respond_to(:username=)
75
+ end
72
76
  end
73
77
 
74
78
  describe "when activated with sorcery" do
75
79
  before(:all) { sorcery_reload! }
76
- before(:each) { User.delete_all }
77
-
80
+ before(:each) { User.sorcery_adapter.delete_all }
81
+
78
82
  it "does not add authenticate method to base class", active_record: true do
79
83
  expect(ActiveRecord::Base).not_to respond_to(:authenticate) if defined?(ActiveRecord)
80
84
  end
@@ -131,7 +135,7 @@ shared_examples_for "rails_3_core_model" do
131
135
  describe "registration" do
132
136
 
133
137
  before(:all) { sorcery_reload! }
134
- before(:each) { User.delete_all }
138
+ before(:each) { User.sorcery_adapter.delete_all }
135
139
 
136
140
  it "by default, encryption_provider is not nil" do
137
141
  expect(User.sorcery_config.encryption_provider).not_to be_nil
@@ -161,13 +165,10 @@ shared_examples_for "rails_3_core_model" do
161
165
  user.password = '4blupush'
162
166
  user.username = nil
163
167
 
164
- User.class_eval { validates_presence_of :username }
168
+ expect(user).to receive(:save) { raise RuntimeError }
169
+
165
170
  begin
166
- if defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource)
167
- user.save
168
- else
169
- user.save! # triggers validation exception since username field is required.
170
- end
171
+ user.save
171
172
  rescue
172
173
  end
173
174
 
@@ -176,32 +177,21 @@ shared_examples_for "rails_3_core_model" do
176
177
 
177
178
  it "does not encrypt the password twice when a user is updated" do
178
179
  user.email = "blup@bla.com"
179
- if defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource)
180
- user.save
181
- else
182
- user.save!
183
- end
180
+ user.save
184
181
 
185
182
  expect(User.sorcery_config.encryption_provider.matches? crypted_password, 'secret', user.salt).to be true
186
183
  end
187
184
 
188
185
  it "replaces the crypted_password in case a new password is set" do
189
186
  user.password = 'new_secret'
190
- if defined?(DataMapper) && user.class.ancestors.include?(DataMapper::Resource)
191
- user.save
192
- else
193
- user.save!
194
- end
187
+ user.save
195
188
 
196
189
  expect(User.sorcery_config.encryption_provider.matches? crypted_password, 'secret', user.salt).to be false
197
190
  end
198
191
 
199
192
  describe "when user has password_confirmation_defined" do
200
193
  before(:all) do
201
- User.class_eval { attr_accessor :password_confirmation }
202
- if defined?(DataMapper)
203
- DataMapper.finalize
204
- end
194
+ update_model { attr_accessor :password_confirmation }
205
195
  end
206
196
 
207
197
  after(:all) do
@@ -227,6 +217,21 @@ shared_examples_for "rails_3_core_model" do
227
217
  end
228
218
  end
229
219
 
220
+ describe "password validation" do
221
+
222
+ let(:user_with_pass) { create_new_user({:username => 'foo_bar', :email => "foo@bar.com", :password => 'foobar'})}
223
+
224
+ specify { expect(user_with_pass).to respond_to :valid_password? }
225
+
226
+ it "returns true if password is correct" do
227
+ expect(user_with_pass.valid_password?("foobar")).to be true
228
+ end
229
+
230
+ it "returns false if password is incorrect" do
231
+ expect(user_with_pass.valid_password?("foobug")).to be false
232
+ end
233
+ end
234
+
230
235
  describe "special encryption cases" do
231
236
  before(:all) do
232
237
  sorcery_reload!()
@@ -234,7 +239,7 @@ shared_examples_for "rails_3_core_model" do
234
239
  end
235
240
 
236
241
  before(:each) do
237
- User.delete_all
242
+ User.sorcery_adapter.delete_all
238
243
  end
239
244
 
240
245
  after(:each) do
@@ -344,13 +349,13 @@ shared_examples_for "rails_3_core_model" do
344
349
  describe "ORM adapter" do
345
350
  before(:all) do
346
351
  sorcery_reload!()
347
- User.delete_all
352
+ User.sorcery_adapter.delete_all
348
353
  end
349
354
 
350
355
  before(:each) { user }
351
356
 
352
357
  after(:each) do
353
- User.delete_all
358
+ User.sorcery_adapter.delete_all
354
359
  User.sorcery_config.reset!
355
360
  end
356
361
 
@@ -358,17 +363,17 @@ shared_examples_for "rails_3_core_model" do
358
363
  it "find_by_username works as expected" do
359
364
  sorcery_model_property_set(:username_attribute_names, [:username])
360
365
 
361
- expect(User.find_by_username "gizmo").to eq user
366
+ expect(User.sorcery_adapter.find_by_username "gizmo").to eq user
362
367
  end
363
368
 
364
369
  it "find_by_username works as expected with multiple username attributes" do
365
370
  sorcery_model_property_set(:username_attribute_names, [:username, :email])
366
371
 
367
- expect(User.find_by_username "gizmo").to eq user
372
+ expect(User.sorcery_adapter.find_by_username "gizmo").to eq user
368
373
  end
369
374
 
370
375
  it "find_by_email works as expected" do
371
- expect(User.find_by_email "bla@bla.com").to eq user
376
+ expect(User.sorcery_adapter.find_by_email "bla@bla.com").to eq user
372
377
  end
373
378
  end
374
379
  end
@@ -378,7 +383,7 @@ shared_examples_for "external_user" do
378
383
  let(:external_user) { create_new_external_user :twitter }
379
384
 
380
385
  before(:each) do
381
- User.delete_all
386
+ User.sorcery_adapter.delete_all
382
387
  end
383
388
 
384
389
  it "responds to 'external?'" do
@@ -392,4 +397,86 @@ shared_examples_for "external_user" do
392
397
  it "external? is true for external users" do
393
398
  expect(external_user.external?).to be true
394
399
  end
400
+
401
+ describe ".create_from_provider" do
402
+
403
+ before(:all) do
404
+ if SORCERY_ORM == :active_record
405
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
406
+ User.reset_column_information
407
+ end
408
+
409
+ sorcery_reload!([:external])
410
+ end
411
+
412
+ after(:all) do
413
+ if SORCERY_ORM == :active_record
414
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
415
+ end
416
+ end
417
+
418
+ it 'supports nested attributes' do
419
+ sorcery_model_property_set(:authentications_class, Authentication)
420
+
421
+ expect { User.create_from_provider('facebook', '123', {username: 'Noam Ben Ari'}) }.to change { User.count }.by(1)
422
+ expect(User.first.username).to eq 'Noam Ben Ari'
423
+ end
424
+
425
+ context 'with block' do
426
+ it 'create user when block return true' do
427
+ expect {
428
+ User.create_from_provider('facebook', '123', {username: 'Noam Ben Ari'}) { true }
429
+ }.to change { User.count }.by(1)
430
+ end
431
+
432
+ it 'does not create user when block return false' do
433
+ expect {
434
+ User.create_from_provider('facebook', '123', {username: 'Noam Ben Ari'}) { false }
435
+ }.not_to change { User.count }
436
+ end
437
+ end
438
+
439
+ end
440
+
441
+ describe 'activation' do
442
+ before(:all) do
443
+ if SORCERY_ORM == :active_record
444
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
445
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
446
+ end
447
+
448
+ sorcery_reload!([:user_activation,:external], :user_activation_mailer => ::SorceryMailer)
449
+ end
450
+
451
+ after(:all) do
452
+ if SORCERY_ORM == :active_record
453
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
454
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
455
+ end
456
+ end
457
+
458
+ after(:each) do
459
+ User.sorcery_adapter.delete_all
460
+ end
461
+
462
+ [:facebook, :github, :google, :liveid].each do |provider|
463
+
464
+ it "does not send activation email to external users" do
465
+ old_size = ActionMailer::Base.deliveries.size
466
+ create_new_external_user(provider)
467
+
468
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
469
+ end
470
+
471
+ it "does not send external users an activation success email" do
472
+ sorcery_model_property_set(:activation_success_email_method_name, nil)
473
+ create_new_external_user(provider)
474
+ old_size = ActionMailer::Base.deliveries.size
475
+ @user.activate!
476
+
477
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
478
+ end
479
+ end
480
+
481
+ end
395
482
  end