devise 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

@@ -1,3 +1,12 @@
1
+ == 3.0.1
2
+
3
+ * enhancements
4
+ * Add after_confirmation callback
5
+
6
+ * bug fix
7
+ * When using rails 3.2, the generator adds 'attr_accessible' to the model (by @jcoyne)
8
+ * Clean up CSRF token after authentication (by @homakov). Notice this change will clean up the CSRF Token after authentication (sign in, sign up, etc). So if you are using AJAX for such features, you will need to fetch a new CSRF token from the server.
9
+
1
10
  == 3.0.0
2
11
 
3
12
  * enhancements
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- devise (3.0.0.rc)
15
+ devise (3.0.0)
16
16
  bcrypt-ruby (~> 3.0)
17
17
  orm_adapter (~> 0.1)
18
18
  railties (>= 3.2.6, < 5)
data/README.md CHANGED
@@ -12,7 +12,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
12
12
 
13
13
  * Is Rack based;
14
14
  * Is a complete MVC solution based on Rails engines;
15
- * Allows you to have multiple roles (or models/scopes) signed in at the same time;
15
+ * Allows you to have multiple models signed in at the same time;
16
16
  * Is based on a modularity concept: use just what you really need.
17
17
 
18
18
  It's composed of 11 modules:
@@ -202,7 +202,7 @@ class ApplicationController < ActionController::Base
202
202
  end
203
203
  ```
204
204
 
205
- If you have multiple roles, you may want to set up different parameter sanitizer per role. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and add your own logic:
205
+ If you have multiple Devise models, you may want to set up different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and add your own logic:
206
206
 
207
207
  ```ruby
208
208
  class User::ParameterSanitizer < Devise::ParameterSanitizer
@@ -240,7 +240,7 @@ Since Devise is an engine, all its views are packaged inside the gem. These view
240
240
  rails generate devise:views
241
241
  ```
242
242
 
243
- If you have more than one role in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all roles. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
243
+ If you have more than one Devise model in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
244
244
 
245
245
  After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new". You can also use the generator to generate scoped views:
246
246
 
@@ -384,7 +384,7 @@ You can read more about Omniauth support in the wiki:
384
384
 
385
385
  ### Configuring multiple models
386
386
 
387
- Devise allows you to set up as many roles as you want. For example, you may have a User model and also want an Admin model with just authentication and timeoutable features. If so, just follow these steps:
387
+ Devise allows you to set up as many Devise models as you want. If you want to have an Admin model with just authentication and timeout features, in addition to the User model above, just run:
388
388
 
389
389
  ```ruby
390
390
  # Create a migration with the required fields
@@ -409,7 +409,9 @@ current_admin
409
409
  admin_session
410
410
  ```
411
411
 
412
- On the other hand, you can simply run the generator!
412
+ Alternatively, you can simply run the Devise generator.
413
+
414
+ Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend you to use a role-based approach, by either providing a role column or using [CanCan](https://github.com/ryanb/cancan).
413
415
 
414
416
  ### Other ORMs
415
417
 
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- devise (3.0.0.rc)
4
+ devise (3.0.0)
5
5
  bcrypt-ruby (~> 3.0)
6
6
  orm_adapter (~> 0.1)
7
7
  railties (>= 3.2.6, < 5)
8
- warden (~> 1.2.1)
8
+ warden (~> 1.2.3)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
@@ -38,7 +38,7 @@ GEM
38
38
  i18n (= 0.6.1)
39
39
  multi_json (~> 1.0)
40
40
  arel (3.0.2)
41
- bcrypt-ruby (3.0.1)
41
+ bcrypt-ruby (3.1.1)
42
42
  builder (3.0.4)
43
43
  erubis (2.7.0)
44
44
  faraday (0.8.7)
@@ -129,7 +129,7 @@ GEM
129
129
  polyglot
130
130
  polyglot (>= 0.3.1)
131
131
  tzinfo (0.3.37)
132
- warden (1.2.1)
132
+ warden (1.2.3)
133
133
  rack (>= 1.0)
134
134
  webrat (0.7.3)
135
135
  nokogiri (>= 1.2.0)
@@ -223,6 +223,10 @@ module Devise
223
223
  mattr_accessor :omniauth_path_prefix
224
224
  @@omniauth_path_prefix = nil
225
225
 
226
+ # Set if we should clean up the CSRF Token on authentication
227
+ mattr_accessor :clean_up_csrf_token_on_authentication
228
+ @@clean_up_csrf_token_on_authentication = true
229
+
226
230
  def self.encryptor=(value)
227
231
  warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
228
232
  end
@@ -0,0 +1,5 @@
1
+ Warden::Manager.after_authentication do |record, warden, options|
2
+ if Devise.clean_up_csrf_token_on_authentication
3
+ warden.request.session.try(:delete, :_csrf_token)
4
+ end
5
+ end
@@ -1,4 +1,5 @@
1
1
  require 'devise/hooks/activatable'
2
+ require 'devise/hooks/csrf_cleaner'
2
3
 
3
4
  module Devise
4
5
  module Models
@@ -66,7 +66,7 @@ module Devise
66
66
  self.confirmation_token = nil
67
67
  self.confirmed_at = Time.now.utc
68
68
 
69
- if self.class.reconfirmable && unconfirmed_email.present?
69
+ saved = if self.class.reconfirmable && unconfirmed_email.present?
70
70
  skip_reconfirmation!
71
71
  self.email = unconfirmed_email
72
72
  self.unconfirmed_email = nil
@@ -76,6 +76,9 @@ module Devise
76
76
  else
77
77
  save(:validate => false)
78
78
  end
79
+
80
+ after_confirmation if saved
81
+ saved
79
82
  end
80
83
  end
81
84
 
@@ -264,6 +267,9 @@ module Devise
264
267
  confirmation_required? && !@skip_confirmation_notification && !self.email.blank?
265
268
  end
266
269
 
270
+ def after_confirmation
271
+ end
272
+
267
273
  module ClassMethods
268
274
  # Attempt to find a user by its email. If a record is found, send new
269
275
  # confirmation instructions to it. If not, try searching for a user by unconfirmed_email
@@ -37,7 +37,7 @@ module Devise
37
37
  private
38
38
 
39
39
  def remember_exists_and_not_expired?
40
- return false unless respond_to?(:remember_created_at)
40
+ return false unless respond_to?(:remember_created_at) && respond_to?(:remember_expired?)
41
41
  remember_created_at && !remember_expired?
42
42
  end
43
43
 
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "3.0.0".freeze
2
+ VERSION = "3.0.1".freeze
3
3
  end
@@ -2,7 +2,7 @@ module Devise
2
2
  module Generators
3
3
  module OrmHelpers
4
4
  def model_contents
5
- <<-CONTENT
5
+ buffer = <<-CONTENT
6
6
  # Include default devise modules. Others available are:
7
7
  # :token_authenticatable, :confirmable,
8
8
  # :lockable, :timeoutable and :omniauthable
@@ -10,16 +10,36 @@ module Devise
10
10
  :recoverable, :rememberable, :trackable, :validatable
11
11
 
12
12
  CONTENT
13
+ buffer += <<-CONTENT if needs_attr_accessible?
14
+ # Setup accessible (or protected) attributes for your model
15
+ attr_accessible :email, :password, :password_confirmation, :remember_me
16
+
17
+ CONTENT
18
+ buffer
19
+ end
20
+
21
+ def needs_attr_accessible?
22
+ rails_3? && !strong_parameters_enabled?
23
+ end
24
+
25
+ def rails_3?
26
+ Rails::VERSION::MAJOR == 3
13
27
  end
14
28
 
29
+ def strong_parameters_enabled?
30
+ defined?(ActionController::StrongParameters)
31
+ end
32
+
33
+ private
34
+
15
35
  def model_exists?
16
36
  File.exists?(File.join(destination_root, model_path))
17
37
  end
18
-
38
+
19
39
  def migration_exists?(table_name)
20
40
  Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
21
41
  end
22
-
42
+
23
43
  def migration_path
24
44
  @migration_path ||= File.join("db", "migrate")
25
45
  end
@@ -29,4 +49,4 @@ CONTENT
29
49
  end
30
50
  end
31
51
  end
32
- end
52
+ end
@@ -22,7 +22,7 @@ module Mongoid
22
22
  ## Database authenticatable
23
23
  field :email, :type => String, :default => ""
24
24
  field :encrypted_password, :type => String, :default => ""
25
-
25
+
26
26
  ## Recoverable
27
27
  field :reset_password_token, :type => String
28
28
  field :reset_password_sent_at, :type => Time
@@ -54,4 +54,4 @@ RUBY
54
54
  end
55
55
  end
56
56
  end
57
- end
57
+ end
@@ -76,6 +76,12 @@ Devise.setup do |config|
76
76
  # passing :skip => :sessions to `devise_for` in your config/routes.rb
77
77
  config.skip_session_storage = [:http_auth]
78
78
 
79
+ # By default, Devise cleans up the CSRF token on authentication to
80
+ # avoid CSRF token fixation attacks. This means that, when using AJAX
81
+ # requests for sign in and sign up, you need to get a new CSRF token
82
+ # from the server. You can disable this option at your own risk.
83
+ # config.clean_up_csrf_token_on_authentication = true
84
+
79
85
  # ==> Configuration for :database_authenticatable
80
86
  # For bcrypt, this is the cost for hashing the password and defaults to 10. If
81
87
  # using other encryptors, it sets how many times you want the password re-encrypted.
@@ -62,11 +62,41 @@ if DEVISE_ORM == :active_record
62
62
  destination File.expand_path("../../tmp", __FILE__)
63
63
  setup :prepare_destination
64
64
 
65
- test "all files are properly created" do
65
+ test "all files are properly created in rails 4.0" do
66
+ ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(false)
66
67
  simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
67
68
  run_generator ["monster"]
68
69
 
69
70
  assert_file "app/models/rails_engine/monster.rb", /devise/
71
+ assert_file "app/models/rails_engine/monster.rb" do |content|
72
+ assert_no_match /attr_accessible :email/, content
73
+ end
74
+ end
75
+ end
76
+
77
+ test "all files are properly created in rails 3.2 when strong_parameters gem is not installed" do
78
+ ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
79
+ ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(false)
80
+ simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
81
+ run_generator ["monster"]
82
+
83
+ assert_file "app/models/rails_engine/monster.rb", /devise/
84
+ assert_file "app/models/rails_engine/monster.rb" do |content|
85
+ assert_match /attr_accessible :email/, content
86
+ end
87
+ end
88
+ end
89
+
90
+ test "all files are properly created in rails 3.2 when strong_parameters gem is installed" do
91
+ ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
92
+ ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(true)
93
+ simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
94
+ run_generator ["monster"]
95
+
96
+ assert_file "app/models/rails_engine/monster.rb", /devise/
97
+ assert_file "app/models/rails_engine/monster.rb" do |content|
98
+ assert_no_match /attr_accessible :email/, content
99
+ end
70
100
  end
71
101
  end
72
102
  end
@@ -327,6 +327,20 @@ class AuthenticationSessionTest < ActionDispatch::IntegrationTest
327
327
  assert_redirected_to new_user_session_path
328
328
  end
329
329
 
330
+ test 'refreshes _csrf_token' do
331
+ ApplicationController.allow_forgery_protection = true
332
+
333
+ begin
334
+ get new_user_session_path
335
+ token = request.session[:_csrf_token]
336
+
337
+ sign_in_as_user
338
+ assert_not_equal request.session[:_csrf_token], token
339
+ ensure
340
+ ApplicationController.allow_forgery_protection = false
341
+ end
342
+ end
343
+
330
344
  test 'allows session to be set for a given scope' do
331
345
  sign_in_as_user
332
346
  get '/users'
@@ -312,6 +312,27 @@ class ConfirmableTest < ActiveSupport::TestCase
312
312
  user.ensure_confirmation_token!
313
313
  assert_equal user.confirmation_token, old
314
314
  end
315
+
316
+ test 'should call after_confirmation if confirmed' do
317
+ user = create_user
318
+ user.define_singleton_method :after_confirmation do
319
+ self.username = self.username.to_s + 'updated'
320
+ end
321
+ old = user.username
322
+ assert user.confirm!
323
+ assert_not_equal user.username, old
324
+ end
325
+
326
+ test 'should not call after_confirmation if not confirmed' do
327
+ user = create_user
328
+ assert user.confirm!
329
+ user.define_singleton_method :after_confirmation do
330
+ self.username = self.username.to_s + 'updated'
331
+ end
332
+ old = user.username
333
+ assert_not user.confirm!
334
+ assert_equal user.username, old
335
+ end
315
336
  end
316
337
 
317
338
  class ReconfirmableTest < ActiveSupport::TestCase
@@ -43,4 +43,9 @@ class TimeoutableTest < ActiveSupport::TestCase
43
43
  test 'required_fields should contain the fields that Devise uses' do
44
44
  assert_same_content Devise::Models::Timeoutable.required_fields(User), []
45
45
  end
46
+
47
+ test 'should not raise error if remember_created_at is not empty and rememberable is disabled' do
48
+ user = create_admin(remember_created_at: Time.current)
49
+ assert user.timedout?(31.minutes.ago)
50
+ end
46
51
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: devise
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 3.0.0
5
+ version: 3.0.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - José Valim
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-14 00:00:00.000000000 Z
13
+ date: 2013-08-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  version_requirements: !ruby/object:Gem::Requirement
@@ -132,6 +132,7 @@ files:
132
132
  - lib/devise/delegator.rb
133
133
  - lib/devise/failure_app.rb
134
134
  - lib/devise/hooks/activatable.rb
135
+ - lib/devise/hooks/csrf_cleaner.rb
135
136
  - lib/devise/hooks/forgetable.rb
136
137
  - lib/devise/hooks/lockable.rb
137
138
  - lib/devise/hooks/rememberable.rb