cbsorcery 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/.document +5 -0
  2. data/.gitignore +56 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +40 -0
  5. data/CHANGELOG.md +263 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +360 -0
  9. data/Rakefile +6 -0
  10. data/gemfiles/active_record-rails40.gemfile +7 -0
  11. data/gemfiles/active_record-rails41.gemfile +7 -0
  12. data/lib/generators/sorcery/USAGE +22 -0
  13. data/lib/generators/sorcery/helpers.rb +40 -0
  14. data/lib/generators/sorcery/install_generator.rb +95 -0
  15. data/lib/generators/sorcery/templates/initializer.rb +451 -0
  16. data/lib/generators/sorcery/templates/migration/activity_logging.rb +10 -0
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +9 -0
  18. data/lib/generators/sorcery/templates/migration/core.rb +13 -0
  19. data/lib/generators/sorcery/templates/migration/external.rb +12 -0
  20. data/lib/generators/sorcery/templates/migration/remember_me.rb +8 -0
  21. data/lib/generators/sorcery/templates/migration/reset_password.rb +9 -0
  22. data/lib/generators/sorcery/templates/migration/user_activation.rb +9 -0
  23. data/lib/sorcery.rb +85 -0
  24. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  25. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  26. data/lib/sorcery/controller.rb +157 -0
  27. data/lib/sorcery/controller/config.rb +65 -0
  28. data/lib/sorcery/controller/submodules/activity_logging.rb +82 -0
  29. data/lib/sorcery/controller/submodules/brute_force_protection.rb +38 -0
  30. data/lib/sorcery/controller/submodules/external.rb +199 -0
  31. data/lib/sorcery/controller/submodules/http_basic_auth.rb +74 -0
  32. data/lib/sorcery/controller/submodules/remember_me.rb +81 -0
  33. data/lib/sorcery/controller/submodules/session_timeout.rb +56 -0
  34. data/lib/sorcery/crypto_providers/aes256.rb +51 -0
  35. data/lib/sorcery/crypto_providers/bcrypt.rb +97 -0
  36. data/lib/sorcery/crypto_providers/common.rb +35 -0
  37. data/lib/sorcery/crypto_providers/md5.rb +19 -0
  38. data/lib/sorcery/crypto_providers/sha1.rb +28 -0
  39. data/lib/sorcery/crypto_providers/sha256.rb +36 -0
  40. data/lib/sorcery/crypto_providers/sha512.rb +36 -0
  41. data/lib/sorcery/engine.rb +21 -0
  42. data/lib/sorcery/model.rb +183 -0
  43. data/lib/sorcery/model/config.rb +96 -0
  44. data/lib/sorcery/model/submodules/activity_logging.rb +70 -0
  45. data/lib/sorcery/model/submodules/brute_force_protection.rb +125 -0
  46. data/lib/sorcery/model/submodules/external.rb +100 -0
  47. data/lib/sorcery/model/submodules/remember_me.rb +62 -0
  48. data/lib/sorcery/model/submodules/reset_password.rb +131 -0
  49. data/lib/sorcery/model/submodules/user_activation.rb +149 -0
  50. data/lib/sorcery/model/temporary_token.rb +30 -0
  51. data/lib/sorcery/protocols/certs/ca-bundle.crt +5182 -0
  52. data/lib/sorcery/protocols/oauth.rb +42 -0
  53. data/lib/sorcery/protocols/oauth2.rb +47 -0
  54. data/lib/sorcery/providers/base.rb +27 -0
  55. data/lib/sorcery/providers/facebook.rb +63 -0
  56. data/lib/sorcery/providers/github.rb +51 -0
  57. data/lib/sorcery/providers/google.rb +51 -0
  58. data/lib/sorcery/providers/jira.rb +77 -0
  59. data/lib/sorcery/providers/linkedin.rb +66 -0
  60. data/lib/sorcery/providers/liveid.rb +53 -0
  61. data/lib/sorcery/providers/twitter.rb +59 -0
  62. data/lib/sorcery/providers/vk.rb +63 -0
  63. data/lib/sorcery/providers/xing.rb +64 -0
  64. data/lib/sorcery/railties/tasks.rake +6 -0
  65. data/lib/sorcery/test_helpers/internal.rb +78 -0
  66. data/lib/sorcery/test_helpers/internal/rails.rb +68 -0
  67. data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
  68. data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
  69. data/lib/sorcery/version.rb +3 -0
  70. data/sorcery.gemspec +34 -0
  71. data/spec/active_record/user_activation_spec.rb +18 -0
  72. data/spec/active_record/user_activity_logging_spec.rb +17 -0
  73. data/spec/active_record/user_brute_force_protection_spec.rb +16 -0
  74. data/spec/active_record/user_oauth_spec.rb +16 -0
  75. data/spec/active_record/user_remember_me_spec.rb +16 -0
  76. data/spec/active_record/user_reset_password_spec.rb +16 -0
  77. data/spec/active_record/user_spec.rb +37 -0
  78. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  79. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  80. data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
  81. data/spec/controllers/controller_oauth2_spec.rb +407 -0
  82. data/spec/controllers/controller_oauth_spec.rb +240 -0
  83. data/spec/controllers/controller_remember_me_spec.rb +117 -0
  84. data/spec/controllers/controller_session_timeout_spec.rb +80 -0
  85. data/spec/controllers/controller_spec.rb +215 -0
  86. data/spec/orm/active_record.rb +21 -0
  87. data/spec/rails_app/app/active_record/authentication.rb +3 -0
  88. data/spec/rails_app/app/active_record/user.rb +5 -0
  89. data/spec/rails_app/app/active_record/user_provider.rb +3 -0
  90. data/spec/rails_app/app/controllers/sorcery_controller.rb +265 -0
  91. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  92. data/spec/rails_app/app/mailers/sorcery_mailer.rb +32 -0
  93. data/spec/rails_app/app/views/application/index.html.erb +17 -0
  94. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  95. data/spec/rails_app/app/views/sorcery_mailer/activation_email.html.erb +17 -0
  96. data/spec/rails_app/app/views/sorcery_mailer/activation_email.text.erb +9 -0
  97. data/spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb +17 -0
  98. data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
  99. data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
  100. data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
  101. data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
  102. data/spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
  103. data/spec/rails_app/config.ru +4 -0
  104. data/spec/rails_app/config/application.rb +56 -0
  105. data/spec/rails_app/config/boot.rb +4 -0
  106. data/spec/rails_app/config/database.yml +22 -0
  107. data/spec/rails_app/config/environment.rb +5 -0
  108. data/spec/rails_app/config/environments/test.rb +37 -0
  109. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  110. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  111. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  112. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  113. data/spec/rails_app/config/initializers/session_store.rb +12 -0
  114. data/spec/rails_app/config/locales/en.yml +5 -0
  115. data/spec/rails_app/config/routes.rb +48 -0
  116. data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  117. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +19 -0
  118. data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +13 -0
  119. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +16 -0
  120. data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +22 -0
  121. data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  122. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  123. data/spec/rails_app/db/schema.rb +23 -0
  124. data/spec/rails_app/db/seeds.rb +7 -0
  125. data/spec/shared_examples/user_activation_shared_examples.rb +242 -0
  126. data/spec/shared_examples/user_activity_logging_shared_examples.rb +97 -0
  127. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +156 -0
  128. data/spec/shared_examples/user_oauth_shared_examples.rb +36 -0
  129. data/spec/shared_examples/user_remember_me_shared_examples.rb +57 -0
  130. data/spec/shared_examples/user_reset_password_shared_examples.rb +263 -0
  131. data/spec/shared_examples/user_shared_examples.rb +467 -0
  132. data/spec/sorcery_crypto_providers_spec.rb +198 -0
  133. data/spec/spec.opts +2 -0
  134. data/spec/spec_helper.rb +41 -0
  135. metadata +350 -0
@@ -0,0 +1,240 @@
1
+ require 'spec_helper'
2
+
3
+ # require 'shared_examples/controller_oauth_shared_examples'
4
+ require 'ostruct'
5
+
6
+ def stub_all_oauth_requests!
7
+ consumer = OAuth::Consumer.new("key","secret", :site => "http://myapi.com")
8
+ req_token = OAuth::RequestToken.new(consumer)
9
+ acc_token = OAuth::AccessToken.new(consumer)
10
+
11
+ response = OpenStruct.new()
12
+ response.body = {"following"=>false, "listed_count"=>0, "profile_link_color"=>"0084B4", "profile_image_url"=>"http://a1.twimg.com/profile_images/536178575/noamb_normal.jpg", "description"=>"Programmer/Heavy Metal Fan/New Father", "status"=>{"text"=>"coming soon to sorcery gem: twitter and facebook authentication support.", "truncated"=>false, "favorited"=>false, "source"=>"web", "geo"=>nil, "in_reply_to_screen_name"=>nil, "in_reply_to_user_id"=>nil, "in_reply_to_status_id_str"=>nil, "created_at"=>"Sun Mar 06 23:01:12 +0000 2011", "contributors"=>nil, "place"=>nil, "retweeted"=>false, "in_reply_to_status_id"=>nil, "in_reply_to_user_id_str"=>nil, "coordinates"=>nil, "retweet_count"=>0, "id"=>44533012284706816, "id_str"=>"44533012284706816"}, "show_all_inline_media"=>false, "geo_enabled"=>true, "profile_sidebar_border_color"=>"a8c7f7", "url"=>nil, "followers_count"=>10, "screen_name"=>"nbenari", "profile_use_background_image"=>true, "location"=>"Israel", "statuses_count"=>25, "profile_background_color"=>"022330", "lang"=>"en", "verified"=>false, "notifications"=>false, "profile_background_image_url"=>"http://a3.twimg.com/profile_background_images/104087198/04042010339.jpg", "favourites_count"=>5, "created_at"=>"Fri Nov 20 21:58:19 +0000 2009", "is_translator"=>false, "contributors_enabled"=>false, "protected"=>false, "follow_request_sent"=>false, "time_zone"=>"Greenland", "profile_text_color"=>"333333", "name"=>"Noam Ben Ari", "friends_count"=>10, "profile_sidebar_fill_color"=>"C0DFEC", "id"=>123, "id_str"=>"91434812", "profile_background_tile"=>false, "utc_offset"=>-10800}.to_json
13
+
14
+ session[:request_token] = req_token.token
15
+ session[:request_token_secret] = req_token.secret
16
+
17
+ allow(OAuth::Consumer).to receive(:new) { consumer }
18
+ allow(consumer).to receive(:get_request_token) { req_token }
19
+ allow(req_token).to receive(:get_access_token) { acc_token }
20
+ allow(OAuth::RequestToken).to receive(:new) { req_token }
21
+ allow(acc_token).to receive(:get) { response }
22
+ end
23
+
24
+ describe SorceryController do
25
+
26
+ let(:user) { double('user', id: 42) }
27
+
28
+ before(:all) do
29
+ sorcery_reload!([:external])
30
+ sorcery_controller_property_set(:external_providers, [:twitter, :jira])
31
+ sorcery_controller_external_property_set(:twitter, :key, "eYVNBjBDi33aa9GkA3w")
32
+ sorcery_controller_external_property_set(:twitter, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
33
+ sorcery_controller_external_property_set(:twitter, :callback_url, "http://blabla.com")
34
+
35
+ sorcery_controller_external_property_set(:jira, :key, "7810b8e317ebdc81601c72f8daecc0f1")
36
+ sorcery_controller_external_property_set(:jira, :secret, "MyAppUsingJira")
37
+ sorcery_controller_external_property_set(:jira, :site, "http://jira.mycompany.com/plugins/servlet/oauth")
38
+ sorcery_controller_external_property_set(:jira, :signature_method, "RSA-SHA1")
39
+ sorcery_controller_external_property_set(:jira, :private_key_file, "myrsakey.pem")
40
+ sorcery_controller_external_property_set(:jira, :callback_url, "http://myappusingjira.com/home")
41
+ end
42
+
43
+ # ----------------- OAuth -----------------------
44
+ describe SorceryController, "'using external API to login'" do
45
+
46
+ before(:each) do
47
+ stub_all_oauth_requests!
48
+ end
49
+
50
+ context "when callback_url begin with /" do
51
+ before do
52
+ sorcery_controller_external_property_set(:twitter, :callback_url, "/oauth/twitter/callback")
53
+ end
54
+ it "login_at redirects correctly" do
55
+ get :login_at_test
56
+ expect(response).to be_a_redirect
57
+ expect(response).to redirect_to("http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Ftest.host%2Foauth%2Ftwitter%2Fcallback&oauth_token=")
58
+ end
59
+ after do
60
+ sorcery_controller_external_property_set(:twitter, :callback_url, "http://blabla.com")
61
+ end
62
+ end
63
+
64
+ context "when callback_url begin with http://" do
65
+ it "login_at redirects correctly", pending: true do
66
+ get :login_at_test
67
+ expect(response).to be_a_redirect
68
+ expect(response).to redirect_to("http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Fblabla.com&oauth_token=")
69
+ end
70
+ end
71
+
72
+ it "logins if user exists" do
73
+ expect(User).to receive(:load_from_provider).with(:twitter, '123').and_return(user)
74
+
75
+ get :test_login_from, :oauth_verifier => "blablaRERASDFcxvSDFA"
76
+ expect(flash[:notice]).to eq "Success!"
77
+ end
78
+
79
+ it "'login_from' fails if user doesn't exist" do
80
+ expect(User).to receive(:load_from_provider).with(:twitter, '123').and_return(nil)
81
+
82
+ get :test_login_from, :oauth_verifier => "blablaRERASDFcxvSDFA"
83
+ expect(flash[:alert]).to eq "Failed!"
84
+ end
85
+
86
+ it "on successful 'login_from' the user is redirected to the url he originally wanted" do
87
+ expect(User).to receive(:load_from_provider).with(:twitter, '123').and_return(user)
88
+ get :test_return_to_with_external, {}, :return_to_url => "fuu"
89
+ expect(response).to redirect_to("fuu")
90
+ expect(flash[:notice]).to eq "Success!"
91
+ end
92
+
93
+ context "when jira" do
94
+ it "user logins successfully" do
95
+ get :login_at_test_jira
96
+ expect(session[:request_token]).not_to be_nil
97
+ expect(response).to be_a_redirect
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ describe SorceryController do
104
+ describe "using 'create_from'" do
105
+ before(:each) do
106
+ stub_all_oauth_requests!
107
+ end
108
+
109
+ it "creates a new user" do
110
+ sorcery_controller_external_property_set(:twitter, :user_info_mapping, {:username => "screen_name"})
111
+ expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
112
+ expect(User).to receive(:create_from_provider).with('twitter', '123', {username: 'nbenari'}).and_return(user)
113
+
114
+ get :test_create_from_provider, :provider => "twitter"
115
+ end
116
+
117
+ it "supports nested attributes" do
118
+ sorcery_controller_external_property_set(:twitter, :user_info_mapping, {:username => "status/text"})
119
+ expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
120
+ expect(User).to receive(:create_from_provider).with('twitter', '123', {username: 'coming soon to sorcery gem: twitter and facebook authentication support.'}).and_return(user)
121
+
122
+ get :test_create_from_provider, :provider => "twitter"
123
+ end
124
+
125
+ it "does not crash on missing nested attributes" do
126
+ sorcery_controller_external_property_set(:twitter, :user_info_mapping, {:username => "status/text", :created_at => "does/not/exist"})
127
+ expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
128
+ expect(User).to receive(:create_from_provider).with('twitter', '123', {username: 'coming soon to sorcery gem: twitter and facebook authentication support.'}).and_return(user)
129
+
130
+ get :test_create_from_provider, :provider => "twitter"
131
+ end
132
+
133
+ it "binds new provider" do
134
+ sorcery_model_property_set(:authentications_class, UserProvider)
135
+
136
+ allow(user).to receive_message_chain(:sorcery_config, :username_attribute_names, :first) { :username }
137
+ allow(user).to receive(:username).and_return('bla@bla.com')
138
+ login_user(user)
139
+
140
+ expect(user).to receive(:add_provider_to_user).with('twitter', '123')
141
+ get :test_add_second_provider, :provider => "twitter"
142
+ end
143
+
144
+ describe "with a block" do
145
+ it "does not create user" do
146
+ sorcery_model_property_set(:authentications_class, Authentication)
147
+ sorcery_controller_external_property_set(:twitter, :user_info_mapping, {:username => "screen_name"})
148
+
149
+ u = double('user')
150
+ expect(User).to receive(:load_from_provider).with('twitter', '123').and_return(nil)
151
+ expect(User).to receive(:create_from_provider).with('twitter', '123', {username: 'nbenari'}).and_return(u).and_yield(u)
152
+
153
+ get :test_create_from_provider_with_block, :provider => "twitter"
154
+ end
155
+
156
+ end
157
+ end
158
+ end
159
+
160
+ describe SorceryController, "OAuth with user activation features" do
161
+ before(:all) do
162
+ sorcery_reload!([:activity_logging, :external])
163
+ end
164
+
165
+ context "when twitter" do
166
+ before(:each) do
167
+ sorcery_controller_property_set(:register_login_time, true)
168
+ sorcery_controller_property_set(:register_logout_time, false)
169
+ sorcery_controller_property_set(:register_last_activity_time, false)
170
+ sorcery_controller_property_set(:register_last_ip_address, false)
171
+ stub_all_oauth_requests!
172
+ end
173
+
174
+ it "registers login time" do
175
+ now = Time.now.in_time_zone
176
+ Timecop.freeze(now)
177
+ expect(User).to receive(:load_from_provider).and_return(user)
178
+ expect(user).to receive(:set_last_login_at).with(be_within(0.1).of(now))
179
+ get :test_login_from
180
+ Timecop.return
181
+ end
182
+
183
+ it "does not register login time if configured so" do
184
+ sorcery_controller_property_set(:register_login_time, false)
185
+ now = Time.now.in_time_zone
186
+ Timecop.freeze(now)
187
+ expect(User).to receive(:load_from_provider).and_return(user)
188
+ expect(user).to receive(:set_last_login_at).never
189
+ get :test_login_from
190
+ Timecop.return
191
+ end
192
+ end
193
+ end
194
+
195
+ describe SorceryController, "OAuth with session timeout features" do
196
+ before(:all) do
197
+ if SORCERY_ORM == :active_record
198
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
199
+ User.reset_column_information
200
+ end
201
+
202
+ sorcery_reload!([:session_timeout, :external])
203
+ end
204
+
205
+ after(:all) do
206
+ if SORCERY_ORM == :active_record
207
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
208
+ end
209
+ end
210
+
211
+ context "when twitter" do
212
+ before(:each) do
213
+ sorcery_model_property_set(:authentications_class, Authentication)
214
+ sorcery_controller_property_set(:session_timeout,0.5)
215
+ stub_all_oauth_requests!
216
+ end
217
+
218
+ after(:each) do
219
+ Timecop.return
220
+ end
221
+
222
+ it "does not reset session before session timeout" do
223
+ expect(User).to receive(:load_from_provider).with(:twitter, '123').and_return(user)
224
+ get :test_login_from
225
+
226
+ expect(session[:user_id]).not_to be_nil
227
+ expect(flash[:notice]).to eq "Success!"
228
+ end
229
+
230
+ it "resets session after session timeout" do
231
+ get :test_login_from
232
+ Timecop.travel(Time.now.in_time_zone+0.6)
233
+ get :test_should_be_logged_in
234
+
235
+ expect(session[:user_id]).to be_nil
236
+ expect(response).to be_a_redirect
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe SorceryController do
4
+
5
+ let!(:user) { double('user', id: 42) }
6
+
7
+ # ----------------- REMEMBER ME -----------------------
8
+ context "with remember me features" do
9
+
10
+ before(:all) do
11
+ sorcery_reload!([:remember_me])
12
+ end
13
+
14
+ after(:each) do
15
+ session = nil
16
+ cookies = nil
17
+ end
18
+
19
+ before(:each) do
20
+ allow(user).to receive(:remember_me_token)
21
+ allow(user).to receive(:remember_me_token_expires_at)
22
+ allow(user).to receive_message_chain(:sorcery_config, :remember_me_token_attribute_name).and_return(:remember_me_token)
23
+ allow(user).to receive_message_chain(:sorcery_config, :remember_me_token_expires_at_attribute_name).and_return(:remember_me_token_expires_at)
24
+ end
25
+
26
+ it "sets cookie on remember_me!" do
27
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
28
+ expect(user).to receive(:remember_me!)
29
+
30
+ post :test_login_with_remember, :email => 'bla@bla.com', :password => 'secret'
31
+
32
+ expect(cookies.signed["remember_me_token"]).to eq assigns[:current_user].remember_me_token
33
+ end
34
+
35
+ it "clears cookie on forget_me!" do
36
+ cookies["remember_me_token"] == {:value => 'asd54234dsfsd43534', :expires => 3600}
37
+ get :test_logout
38
+
39
+ expect(cookies["remember_me_token"]).to be_nil
40
+ end
41
+
42
+ it "login(email,password,remember_me) logs user in and remembers" do
43
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret', '1').and_return(user)
44
+ expect(user).to receive(:remember_me!)
45
+ expect(user).to receive(:remember_me_token).and_return('abracadabra').twice
46
+
47
+ post :test_login_with_remember_in_login, :email => 'bla@bla.com', :password => 'secret', :remember => "1"
48
+
49
+ expect(cookies.signed["remember_me_token"]).not_to be_nil
50
+ expect(cookies.signed["remember_me_token"]).to eq assigns[:user].remember_me_token
51
+ end
52
+
53
+ it "logout also calls forget_me!" do
54
+ session[:user_id] = user.id.to_s
55
+ expect(User.sorcery_adapter).to receive(:find_by_id).with(user.id.to_s).and_return(user)
56
+ expect(user).to receive(:remember_me!)
57
+ expect(user).to receive(:forget_me!)
58
+ get :test_logout_with_remember
59
+
60
+ expect(cookies["remember_me_token"]).to be_nil
61
+ end
62
+
63
+ it "logs user in from cookie" do
64
+ session[:user_id] = user.id.to_s
65
+ expect(User.sorcery_adapter).to receive(:find_by_id).with(user.id.to_s).and_return(user)
66
+ expect(user).to receive(:remember_me!)
67
+ expect(user).to receive(:remember_me_token).and_return('token').twice
68
+ expect(user).to receive(:has_remember_me_token?) { true }
69
+
70
+ subject.remember_me!
71
+ subject.instance_eval do
72
+ remove_instance_variable :@current_user
73
+ end
74
+ session[:user_id] = nil
75
+
76
+ expect(User.sorcery_adapter).to receive(:find_by_remember_me_token).with('token').and_return(user)
77
+
78
+ get :test_login_from_cookie
79
+
80
+ expect(assigns[:current_user]).to eq user
81
+ end
82
+
83
+ it "doest not remember_me! when not asked to, even if third parameter is used" do
84
+ post :test_login_with_remember_in_login, :email => 'bla@bla.com', :password => 'secret', :remember => "0"
85
+
86
+ expect(cookies["remember_me_token"]).to be_nil
87
+ end
88
+
89
+ it "doest not remember_me! when not asked to" do
90
+ post :test_login, :email => 'bla@bla.com', :password => 'secret'
91
+ expect(cookies["remember_me_token"]).to be_nil
92
+ end
93
+
94
+ # --- login_user(user) ---
95
+ specify { expect(@controller).to respond_to :auto_login }
96
+
97
+ it "auto_login(user) logs in an user instance without remembering" do
98
+ session[:user_id] = nil
99
+ subject.auto_login(user)
100
+ get :test_login_from_cookie
101
+
102
+ expect(assigns[:current_user]).to eq user
103
+ expect(cookies["remember_me_token"]).to be_nil
104
+ end
105
+
106
+ it "auto_login(user, true) logs in an user instance with remembering" do
107
+ session[:user_id] = nil
108
+ expect(user).to receive(:remember_me!)
109
+ subject.auto_login(user, true)
110
+
111
+ get :test_login_from_cookie
112
+
113
+ expect(assigns[:current_user]).to eq user
114
+ expect(cookies["remember_me_token"]).not_to be_nil
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe SorceryController do
4
+
5
+ let!(:user) { double('user', id: 42) }
6
+
7
+ # ----------------- SESSION TIMEOUT -----------------------
8
+ context "with session timeout features" do
9
+ before(:all) do
10
+ sorcery_reload!([:session_timeout])
11
+ sorcery_controller_property_set(:session_timeout,0.5)
12
+ end
13
+
14
+ after(:each) do
15
+ Timecop.return
16
+ end
17
+
18
+ before(:each) do
19
+ allow(user).to receive(:username)
20
+ allow(user).to receive_message_chain(:sorcery_config, :username_attribute_names, :first) { :username }
21
+ end
22
+
23
+ it "does not reset session before session timeout" do
24
+ login_user user
25
+ get :test_should_be_logged_in
26
+
27
+ expect(session[:user_id]).not_to be_nil
28
+ expect(response).to be_a_success
29
+ end
30
+
31
+ it "resets session after session timeout" do
32
+ login_user user
33
+ Timecop.travel(Time.now.in_time_zone+0.6)
34
+ get :test_should_be_logged_in
35
+
36
+ expect(session[:user_id]).to be_nil
37
+ expect(response).to be_a_redirect
38
+ end
39
+
40
+ it "works if the session is stored as a string or a Time" do
41
+ session[:login_time] = Time.now.to_s
42
+ # TODO: ???
43
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
44
+
45
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
46
+
47
+ expect(session[:user_id]).not_to be_nil
48
+ expect(response).to be_a_success
49
+ end
50
+
51
+ context "with 'session_timeout_from_last_action'" do
52
+ it "does not logout if there was activity" do
53
+ sorcery_controller_property_set(:session_timeout_from_last_action, true)
54
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
55
+
56
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
57
+ Timecop.travel(Time.now.in_time_zone+0.3)
58
+ get :test_should_be_logged_in
59
+
60
+ expect(session[:user_id]).not_to be_nil
61
+
62
+ Timecop.travel(Time.now.in_time_zone+0.3)
63
+ get :test_should_be_logged_in
64
+
65
+ expect(session[:user_id]).not_to be_nil
66
+ expect(response).to be_a_success
67
+ end
68
+
69
+ it "with 'session_timeout_from_last_action' logs out if there was no activity" do
70
+ sorcery_controller_property_set(:session_timeout_from_last_action, true)
71
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
72
+ Timecop.travel(Time.now.in_time_zone+0.6)
73
+ get :test_should_be_logged_in
74
+
75
+ expect(session[:user_id]).to be_nil
76
+ expect(response).to be_a_redirect
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper'
2
+
3
+ describe SorceryController do
4
+ describe "plugin configuration" do
5
+ before(:all) do
6
+ sorcery_reload!
7
+ end
8
+
9
+ after(:each) do
10
+ Sorcery::Controller::Config.reset!
11
+ sorcery_reload!
12
+ end
13
+
14
+ it "enables configuration option 'user_class'" do
15
+ sorcery_controller_property_set(:user_class, "TestUser")
16
+
17
+ expect(Sorcery::Controller::Config.user_class).to eq "TestUser"
18
+ end
19
+
20
+ it "enables configuration option 'not_authenticated_action'" do
21
+ sorcery_controller_property_set(:not_authenticated_action, :my_action)
22
+
23
+ expect(Sorcery::Controller::Config.not_authenticated_action).to eq :my_action
24
+ end
25
+
26
+ end
27
+
28
+ # ----------------- PLUGIN ACTIVATED -----------------------
29
+ context "when activated with sorcery" do
30
+ let(:user) { double('user', id: 42) }
31
+
32
+ before(:all) do
33
+ sorcery_reload!
34
+ end
35
+
36
+ after(:each) do
37
+ Sorcery::Controller::Config.reset!
38
+ sorcery_reload!
39
+ sorcery_controller_property_set(:user_class, User)
40
+ sorcery_model_property_set(:username_attribute_names, [:email])
41
+ end
42
+
43
+ specify { should respond_to(:login) }
44
+
45
+ specify { should respond_to(:logout) }
46
+
47
+ specify { should respond_to(:logged_in?) }
48
+
49
+ specify { should respond_to(:current_user) }
50
+
51
+ it "login(username,password) returns the user when success and set the session with user.id" do
52
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
53
+
54
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
55
+
56
+ expect(assigns[:user]).to eq user
57
+ expect(session[:user_id]).to eq "42"
58
+ end
59
+
60
+ it "login(email,password) returns the user when success and set the session with user.id" do
61
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
62
+
63
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
64
+
65
+ expect(assigns[:user]).to eq user
66
+ expect(session[:user_id]).to eq user.id.to_s
67
+ end
68
+
69
+ it "login(username,password) returns nil and not set the session when failure" do
70
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'opensesame!').and_return(nil)
71
+
72
+ get :test_login, :email => 'bla@bla.com', :password => 'opensesame!'
73
+
74
+ expect(assigns[:user]).to be_nil
75
+ expect(session[:user_id]).to be_nil
76
+ end
77
+
78
+ it "login(email,password) returns the user when success and set the session with the _csrf_token" do
79
+ expect(User).to receive(:authenticate).with('bla@bla.com', 'secret').and_return(user)
80
+ get :test_login, :email => 'bla@bla.com', :password => 'secret'
81
+
82
+ expect(session[:_csrf_token]).not_to be_nil
83
+ end
84
+
85
+ it "login(username,password) returns nil and not set the session when upper case username" do
86
+ get :test_login, :email => 'BLA@BLA.COM', :password => 'secret'
87
+
88
+ expect(assigns[:user]).to be_nil
89
+ expect(session[:user_id]).to be_nil
90
+ end
91
+
92
+ # TODO: move test to model
93
+ it "login(username,password) returns the user and set the session with user.id when upper case username and config is downcase before authenticating" do
94
+ sorcery_model_property_set(:downcase_username_before_authenticating, true)
95
+ expect(User).to receive(:authenticate).with('BLA@BLA.COM', 'secret').and_return(user)
96
+ get :test_login, :email => 'BLA@BLA.COM', :password => 'secret'
97
+
98
+ expect(assigns[:user]).to eq user
99
+ expect(session[:user_id]).to eq user.id.to_s
100
+ end
101
+
102
+ # TODO: move test to model
103
+ it "login(username,password) returns nil and not set the session when user was created with upper case username, config is default, and log in username is lower case" do
104
+ expect(User).to receive(:authenticate).with('bla1@bla.com', 'secret1').and_return(nil)
105
+ get :test_login, :email => 'bla1@bla.com', :password => 'secret1'
106
+
107
+ expect(assigns[:user]).to be_nil
108
+ expect(session[:user_id]).to be_nil
109
+ end
110
+
111
+ # TODO: move test to model
112
+ it "login(username,password) returns the user and set the session with user.id when user was created with upper case username and config is downcase before authenticating" do
113
+ sorcery_model_property_set(:downcase_username_before_authenticating, true)
114
+ expect(User).to receive(:authenticate).with('bla1@bla.com', 'secret1').and_return(user)
115
+ get :test_login, :email => 'bla1@bla.com', :password => 'secret1'
116
+
117
+ expect(assigns[:user]).to eq user
118
+ expect(session[:user_id]).to eq user.id.to_s
119
+ end
120
+
121
+ it "logout clears the session" do
122
+ cookies[:remember_me_token] = nil
123
+ session[:user_id] = user.id.to_s
124
+ expect(User.sorcery_adapter).to receive(:find_by_id).with("42") { user }
125
+ get :test_logout
126
+
127
+ expect(session[:user_id]).to be_nil
128
+ end
129
+
130
+ it "logged_in? returns true if logged in" do
131
+ session[:user_id] = user.id.to_s
132
+ expect(User.sorcery_adapter).to receive(:find_by_id).with("42") { user }
133
+
134
+ expect(subject.logged_in?).to be true
135
+ end
136
+
137
+ it "logged_in? returns false if not logged in" do
138
+ session[:user_id] = nil
139
+
140
+ expect(subject.logged_in?).to be false
141
+ end
142
+
143
+ it "current_user returns the user instance if logged in" do
144
+ session[:user_id] = user.id.to_s
145
+ expect(User.sorcery_adapter).to receive(:find_by_id).with("42") { user }
146
+
147
+ 2.times { expect(subject.current_user).to eq user } # memoized!
148
+ end
149
+
150
+ it "current_user returns false if not logged in" do
151
+ session[:user_id] = nil
152
+ expect(User.sorcery_adapter).to_not receive(:find_by_id)
153
+
154
+ 2.times { expect(subject.current_user).to be_nil } # memoized!
155
+ end
156
+
157
+ specify { should respond_to(:require_login) }
158
+
159
+ it "calls the configured 'not_authenticated_action' when authenticate before_filter fails" do
160
+ session[:user_id] = nil
161
+ sorcery_controller_property_set(:not_authenticated_action, :test_not_authenticated_action)
162
+ get :test_logout
163
+
164
+ expect(response.body).to eq "test_not_authenticated_action"
165
+ end
166
+
167
+ it "require_login before_filter saves the url that the user originally wanted" do
168
+ get :some_action
169
+
170
+ expect(session[:return_to_url]).to eq "http://test.host/some_action"
171
+ expect(response).to redirect_to("http://test.host/")
172
+ end
173
+
174
+ it "require_login before_filter does not save the url that the user originally wanted upon all non-get http methods" do
175
+ [:post, :put, :delete].each do |m|
176
+ self.send(m, :some_action)
177
+
178
+ expect(session[:return_to_url]).to be_nil
179
+ end
180
+ end
181
+
182
+ it "on successful login the user is redirected to the url he originally wanted" do
183
+ session[:return_to_url] = "http://test.host/some_action"
184
+ post :test_return_to, :email => 'bla@bla.com', :password => 'secret'
185
+
186
+ expect(response).to redirect_to("http://test.host/some_action")
187
+ expect(flash[:notice]).to eq "haha!"
188
+ end
189
+
190
+
191
+ # --- auto_login(user) ---
192
+ specify { should respond_to(:auto_login) }
193
+
194
+ it "auto_login(user) los in a user instance" do
195
+ session[:user_id] = nil
196
+ subject.auto_login(user)
197
+
198
+ expect(subject.logged_in?).to be true
199
+ end
200
+
201
+ it "auto_login(user) works even if current_user was already set to false" do
202
+ get :test_logout
203
+
204
+ expect(session[:user_id]).to be_nil
205
+ expect(subject.current_user).to be_nil
206
+
207
+ expect(User).to receive(:first) { user }
208
+
209
+ get :test_auto_login
210
+
211
+ expect(assigns[:result]).to eq user
212
+ end
213
+ end
214
+
215
+ end