devise 1.1.rc0 → 1.1.rc1

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.

Files changed (64) hide show
  1. data/CHANGELOG.rdoc +11 -4
  2. data/Gemfile +1 -1
  3. data/README.rdoc +27 -22
  4. data/TODO +0 -1
  5. data/app/helpers/devise_helper.rb +17 -0
  6. data/app/{models → mailers}/devise/mailer.rb +8 -1
  7. data/app/views/devise/confirmations/new.html.erb +2 -2
  8. data/app/views/devise/passwords/edit.html.erb +2 -2
  9. data/app/views/devise/passwords/new.html.erb +2 -2
  10. data/app/views/devise/registrations/edit.html.erb +2 -2
  11. data/app/views/devise/registrations/new.html.erb +3 -2
  12. data/app/views/devise/sessions/new.html.erb +1 -1
  13. data/app/views/devise/shared/_links.erb +1 -1
  14. data/app/views/devise/unlocks/new.html.erb +2 -2
  15. data/config/locales/en.yml +1 -1
  16. data/lib/devise/controllers/internal_helpers.rb +1 -0
  17. data/lib/devise/controllers/scoped_views.rb +1 -1
  18. data/lib/devise/hooks/activatable.rb +1 -20
  19. data/lib/devise/hooks/forgetable.rb +10 -0
  20. data/lib/devise/hooks/rememberable.rb +4 -14
  21. data/lib/devise/mapping.rb +21 -9
  22. data/lib/devise/models.rb +21 -9
  23. data/lib/devise/models/authenticatable.rb +40 -4
  24. data/lib/devise/models/confirmable.rb +0 -4
  25. data/lib/devise/models/database_authenticatable.rb +6 -5
  26. data/lib/devise/models/lockable.rb +6 -10
  27. data/lib/devise/models/rememberable.rb +1 -0
  28. data/lib/devise/models/token_authenticatable.rb +14 -35
  29. data/lib/devise/modules.rb +0 -1
  30. data/lib/devise/rails.rb +2 -0
  31. data/lib/devise/rails/routes.rb +26 -27
  32. data/lib/devise/strategies/authenticatable.rb +0 -12
  33. data/lib/devise/strategies/base.rb +14 -0
  34. data/lib/devise/strategies/database_authenticatable.rb +1 -0
  35. data/lib/devise/strategies/rememberable.rb +3 -1
  36. data/lib/devise/strategies/token_authenticatable.rb +4 -1
  37. data/lib/devise/version.rb +1 -1
  38. data/lib/generators/devise/devise_generator.rb +1 -1
  39. data/lib/generators/devise/templates/migration.rb +2 -0
  40. data/lib/generators/devise_install/templates/README +6 -0
  41. data/lib/generators/devise_views/devise_views_generator.rb +2 -2
  42. data/test/integration/confirmable_test.rb +2 -2
  43. data/test/integration/database_authenticatable_test.rb +7 -7
  44. data/test/integration/lockable_test.rb +10 -2
  45. data/test/integration/recoverable_test.rb +3 -3
  46. data/test/integration/registerable_test.rb +1 -1
  47. data/test/integration/rememberable_test.rb +1 -1
  48. data/test/mapping_test.rb +11 -9
  49. data/test/models/lockable_test.rb +3 -0
  50. data/test/models/token_authenticatable_test.rb +4 -11
  51. data/test/models_test.rb +9 -2
  52. data/test/rails_app/app/active_record/admin.rb +1 -1
  53. data/test/rails_app/app/active_record/user.rb +1 -1
  54. data/test/rails_app/app/data_mapper/admin.rb +1 -2
  55. data/test/rails_app/app/data_mapper/user.rb +1 -1
  56. data/test/rails_app/app/mongoid/admin.rb +1 -1
  57. data/test/rails_app/app/mongoid/user.rb +1 -1
  58. data/test/rails_app/config/application.rb +0 -4
  59. data/test/rails_app/config/environments/test.rb +2 -0
  60. data/test/rails_app/config/initializers/secret_token.rb +2 -0
  61. data/test/rails_app/config/routes.rb +2 -2
  62. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +1 -1
  63. metadata +7 -5
  64. data/lib/devise/models/activatable.rb +0 -16
data/lib/devise/models.rb CHANGED
@@ -1,5 +1,17 @@
1
1
  module Devise
2
2
  module Models
3
+ class << self
4
+ def hook(base)
5
+ base.class_eval do
6
+ class_attribute :devise_modules, :instance_writer => false
7
+ self.devise_modules ||= []
8
+ end
9
+ end
10
+
11
+ alias :included :hook
12
+ alias :extended :hook
13
+ end
14
+
3
15
  # Creates configuration values for Devise and for the given module.
4
16
  #
5
17
  # Devise::Models.config(Devise::Authenticable, :stretches, 10)
@@ -45,7 +57,7 @@ module Devise
45
57
  # for a complete description on those values.
46
58
  #
47
59
  def devise(*modules)
48
- raise "You need to give at least one Devise module" if modules.empty?
60
+ include Devise::Models::Authenticatable
49
61
  options = modules.extract_options!
50
62
 
51
63
  if modules.delete(:authenticatable)
@@ -53,24 +65,22 @@ module Devise
53
65
  modules << :database_authenticatable
54
66
  end
55
67
 
68
+ if modules.delete(:activatable)
69
+ ActiveSupport::Deprecation.warn ":activatable as module is deprecated. It's included in your model by default.", caller
70
+ end
71
+
56
72
  if modules.delete(:http_authenticatable)
57
73
  ActiveSupport::Deprecation.warn ":http_authenticatable as module is deprecated and is on by default. Revert by setting :http_authenticatable => false.", caller
58
74
  end
59
75
 
60
- @devise_modules = Devise::ALL & modules.map(&:to_sym).uniq
76
+ self.devise_modules += Devise::ALL & modules.map(&:to_sym).uniq
61
77
 
62
78
  devise_modules_hook! do
63
- @devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) }
79
+ devise_modules.each { |m| include Devise::Models.const_get(m.to_s.classify) }
64
80
  options.each { |key, value| send(:"#{key}=", value) }
65
81
  end
66
82
  end
67
83
 
68
- # Stores all modules included inside the model, so we are able to verify
69
- # which routes are needed.
70
- def devise_modules
71
- @devise_modules ||= []
72
- end
73
-
74
84
  # The hook which is called inside devise. So your ORM can include devise
75
85
  # compatibility stuff.
76
86
  def devise_modules_hook!
@@ -100,3 +110,5 @@ module Devise
100
110
  end
101
111
  end
102
112
  end
113
+
114
+ require 'devise/models/authenticatable'
@@ -1,8 +1,10 @@
1
+ require 'devise/hooks/activatable'
2
+
1
3
  module Devise
2
4
  module Models
3
5
  # Authenticable module. Holds common settings for authentication.
4
6
  #
5
- # Configuration:
7
+ # == Configuration:
6
8
  #
7
9
  # You can overwrite configuration values by setting in globally in Devise,
8
10
  # using devise method or overwriting the respective instance method.
@@ -15,13 +17,47 @@ module Devise
15
17
  # params_authenticatable: if this model allows authentication through request params. By default true.
16
18
  # It also accepts an array specifying the strategies that should allow params authentication.
17
19
  #
20
+ # == Active?
21
+ #
22
+ # Before authenticating an user and in each request, Devise checks if your model is active by
23
+ # calling model.active?. This method is overwriten by other devise modules. For instance,
24
+ # :confirmable overwrites .active? to only return true if your model was confirmed.
25
+ #
26
+ # You overwrite this method yourself, but if you do, don't forget to call super:
27
+ #
28
+ # def active?
29
+ # super && special_condition_is_valid?
30
+ # end
31
+ #
32
+ # Whenever active? returns false, Devise asks the reason why your model is inactive using
33
+ # the inactive_message method. You can overwrite it as well:
34
+ #
35
+ # def inactive_message
36
+ # special_condition_is_valid? ? super : :special_condition_is_not_valid
37
+ # end
38
+ #
18
39
  module Authenticatable
19
40
  extend ActiveSupport::Concern
20
41
 
21
- # Yields the given block. This method is overwritten by other modules to provide
22
- # hooks around authentication.
42
+ # Check if the current object is valid for authentication. This method and find_for_authentication
43
+ # are the methods used in a Warden::Strategy to check if a model should be signed in or not.
44
+ #
45
+ # However, you should not need to overwrite this method, you should overwrite active? and
46
+ # inactive_message instead.
23
47
  def valid_for_authentication?
24
- yield
48
+ if active?
49
+ block_given? ? yield : true
50
+ else
51
+ inactive_message
52
+ end
53
+ end
54
+
55
+ def active?
56
+ true
57
+ end
58
+
59
+ def inactive_message
60
+ :inactive
25
61
  end
26
62
 
27
63
  module ClassMethods
@@ -1,8 +1,5 @@
1
- require 'devise/models/activatable'
2
-
3
1
  module Devise
4
2
  module Models
5
-
6
3
  # Confirmable is responsible to verify if an account is already confirmed to
7
4
  # sign in, and to send emails with confirmation instructions.
8
5
  # Confirmation instructions are sent to the user email after creating a
@@ -30,7 +27,6 @@ module Devise
30
27
  # User.find(1).resend_confirmation! # generates a new token and resent it
31
28
  module Confirmable
32
29
  extend ActiveSupport::Concern
33
- include Devise::Models::Activatable
34
30
 
35
31
  included do
36
32
  before_create :generate_confirmation_token, :if => :confirmation_required?
@@ -1,4 +1,3 @@
1
- require 'devise/models/authenticatable'
2
1
  require 'devise/strategies/database_authenticatable'
3
2
 
4
3
  module Devise
@@ -25,8 +24,7 @@ module Devise
25
24
  # User.find(1).valid_password?('password123') # returns true/false
26
25
  #
27
26
  module DatabaseAuthenticatable
28
- extend ActiveSupport::Concern
29
- include Devise::Models::Authenticatable
27
+ extend ActiveSupport::Concern
30
28
 
31
29
  included do
32
30
  attr_reader :password, :current_password
@@ -75,6 +73,9 @@ module Devise
75
73
  result
76
74
  end
77
75
 
76
+ def after_database_authentication
77
+ end
78
+
78
79
  protected
79
80
 
80
81
  # Digests the password using the configured encryptor.
@@ -90,8 +91,8 @@ module Devise
90
91
  @encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
91
92
  end
92
93
 
93
- def find_for_database_authentication(*args)
94
- find_for_authentication(*args)
94
+ def find_for_database_authentication(conditions)
95
+ find_for_authentication(conditions)
95
96
  end
96
97
  end
97
98
  end
@@ -1,8 +1,5 @@
1
- require 'devise/models/activatable'
2
-
3
1
  module Devise
4
2
  module Models
5
-
6
3
  # Handles blocking a user access after a certain number of attempts.
7
4
  # Lockable accepts two different strategies to unlock a user after it's
8
5
  # blocked: email and time. The former will send an email to the user when
@@ -20,7 +17,6 @@ module Devise
20
17
  #
21
18
  module Lockable
22
19
  extend ActiveSupport::Concern
23
- include Devise::Models::Activatable
24
20
 
25
21
  delegate :lock_strategy_enabled?, :unlock_strategy_enabled?, :to => "self.class"
26
22
 
@@ -77,15 +73,15 @@ module Devise
77
73
  # for verifying whether an user is allowed to sign in or not. If the user
78
74
  # is locked, it should never be allowed.
79
75
  def valid_for_authentication?
80
- return :locked if access_locked?
81
- return super unless persisted?
82
- return super unless lock_strategy_enabled?(:failed_attempts)
76
+ return super unless persisted? && lock_strategy_enabled?(:failed_attempts)
83
77
 
84
- if result = super
78
+ case (result = super)
79
+ when Symbol
80
+ return result
81
+ when TrueClass
85
82
  self.failed_attempts = 0
86
- else
83
+ when FalseClass
87
84
  self.failed_attempts += 1
88
-
89
85
  if attempts_exceeded?
90
86
  lock_access!
91
87
  return :locked
@@ -1,5 +1,6 @@
1
1
  require 'devise/strategies/rememberable'
2
2
  require 'devise/hooks/rememberable'
3
+ require 'devise/hooks/forgetable'
3
4
 
4
5
  module Devise
5
6
  module Models
@@ -2,8 +2,11 @@ require 'devise/strategies/token_authenticatable'
2
2
 
3
3
  module Devise
4
4
  module Models
5
- # Token Authenticatable Module, responsible for generate authentication token and validating
6
- # authenticity of a user while signing in using an authentication token (say follows an URL).
5
+ # The TokenAuthenticatable module is responsible for generating an authentication token and
6
+ # validating the authenticity of the same while signing in.
7
+ #
8
+ # This module only provides a few helpers to help you manage the token. Creating and resetting
9
+ # the token is your responsibility.
7
10
  #
8
11
  # == Configuration:
9
12
  #
@@ -12,18 +15,8 @@ module Devise
12
15
  #
13
16
  # +token_authentication_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
14
17
  #
15
- # == Examples:
16
- #
17
- # User.authenticate_with_token(:auth_token => '123456789') # returns authenticated user or nil
18
- # User.find(1).valid_authentication_token?('rI1t6PKQ8yP7VetgwdybB') # returns true/false
19
- #
20
18
  module TokenAuthenticatable
21
- extend ActiveSupport::Concern
22
- include Devise::Models::Authenticatable
23
-
24
- included do
25
- before_save :ensure_authentication_token
26
- end
19
+ extend ActiveSupport::Concern
27
20
 
28
21
  # Generate new authentication token (a.k.a. "single access token").
29
22
  def reset_authentication_token
@@ -33,7 +26,7 @@ module Devise
33
26
  # Generate new authentication token and save the record.
34
27
  def reset_authentication_token!
35
28
  reset_authentication_token
36
- self.save
29
+ self.save(:validate => false)
37
30
  end
38
31
 
39
32
  # Generate authentication token unless already exists.
@@ -46,35 +39,21 @@ module Devise
46
39
  self.reset_authentication_token! if self.authentication_token.blank?
47
40
  end
48
41
 
42
+ # Hook called after token authentication.
43
+ def after_token_authentication
44
+ end
45
+
49
46
  module ClassMethods
50
47
  ::Devise::Models.config(self, :token_authentication_key)
51
48
 
52
- # Authenticate a user based on authentication token.
53
- def authenticate_with_token(attributes)
54
- token = attributes[self.token_authentication_key]
55
- self.find_for_token_authentication(token)
49
+ def find_for_token_authentication(conditions)
50
+ conditions[:authentication_token] ||= conditions.delete(token_authentication_key)
51
+ find_for_authentication(conditions)
56
52
  end
57
53
 
58
54
  def authentication_token
59
55
  ::Devise.friendly_token
60
56
  end
61
-
62
- protected
63
-
64
- # Find first record based on conditions given (ie by the sign in form).
65
- # Overwrite to add customized conditions, create a join, or maybe use a
66
- # namedscope to filter records while authenticating.
67
- #
68
- # == Example:
69
- #
70
- # def self.find_for_token_authentication(token, conditions = {})
71
- # conditions = {:active => true}
72
- # super
73
- # end
74
- #
75
- def find_for_token_authentication(token)
76
- self.find(:first, :conditions => { :authentication_token => token})
77
- end
78
57
  end
79
58
  end
80
59
  end
@@ -14,7 +14,6 @@ Devise.with_options :model => true do |d|
14
14
  d.add_module :validatable
15
15
 
16
16
  # The ones which can sign out after
17
- d.add_module :activatable
18
17
  d.add_module :confirmable, :controller => :confirmations, :route => :confirmation
19
18
  d.add_module :lockable, :controller => :unlocks, :route => :unlock
20
19
  d.add_module :timeoutable
data/lib/devise/rails.rb CHANGED
@@ -15,6 +15,8 @@ module Devise
15
15
 
16
16
  initializer "devise.add_url_helpers" do |app|
17
17
  Devise::FailureApp.send :include, app.routes.url_helpers
18
+ ActionController::Base.send :include, Devise::Controllers::UrlHelpers
19
+ ActionView::Base.send :include, Devise::Controllers::UrlHelpers
18
20
  end
19
21
 
20
22
  config.after_initialize do
@@ -6,8 +6,6 @@ module ActionDispatch::Routing
6
6
  finalize_without_devise!
7
7
  Devise.configure_warden!
8
8
  ActionController::Base.send :include, Devise::Controllers::Helpers
9
- ActionController::Base.send :include, Devise::Controllers::UrlHelpers
10
- ActionView::Base.send :include, Devise::Controllers::UrlHelpers
11
9
  end
12
10
  alias_method_chain :finalize!, :devise
13
11
  end
@@ -16,13 +14,14 @@ module ActionDispatch::Routing
16
14
  # Includes devise_for method for routes. This method is responsible to
17
15
  # generate all needed routes for devise, based on what modules you have
18
16
  # defined in your model.
17
+ #
19
18
  # Examples: Let's say you have an User model configured to use
20
19
  # authenticatable, confirmable and recoverable modules. After creating this
21
20
  # inside your routes:
22
21
  #
23
22
  # devise_for :users
24
23
  #
25
- # this method is going to look inside your User model and create the
24
+ # This method is going to look inside your User model and create the
26
25
  # needed routes:
27
26
  #
28
27
  # # Session routes for Authenticatable (default)
@@ -46,44 +45,44 @@ module ActionDispatch::Routing
46
45
  # * :class_name => setup a different class to be looked up by devise,
47
46
  # if it cannot be correctly find by the route name.
48
47
  #
49
- # devise_for :users, :class_name => 'Account'
48
+ # devise_for :users, :class_name => 'Account'
50
49
  #
51
- # * :as => allows you to setup path name that will be used, as rails routes does.
52
- # The following route configuration would setup your route as /accounts instead of /users:
50
+ # * :path => allows you to setup path name that will be used, as rails routes does.
51
+ # The following route configuration would setup your route as /accounts instead of /users:
53
52
  #
54
- # devise_for :users, :as => 'accounts'
53
+ # devise_for :users, :path => 'accounts'
55
54
  #
56
- # * :scope => setup the scope name. This is used as the instance variable name in controller,
57
- # as the name in routes and the scope given to warden. Defaults to the singular of the given name:
55
+ # * :singular => setup the singular name for the given resource. This is used as the instance variable name in
56
+ # controller, as the name in routes and the scope given to warden.
58
57
  #
59
- # devise_for :users, :scope => :account
58
+ # devise_for :users, :singular => :user
60
59
  #
61
60
  # * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
62
61
  # :password, :confirmation, :unlock.
63
62
  #
64
- # devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
63
+ # devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
65
64
  #
66
65
  # * :path_prefix => the path prefix to be used in all routes.
67
66
  #
68
- # devise_for :users, :path_prefix => "/:locale"
67
+ # devise_for :users, :path_prefix => "/:locale"
69
68
  #
70
69
  # If you are using a dynamic prefix, like :locale above, you need to configure default_url_options in your ApplicationController
71
70
  # class level, so Devise can pick it:
72
71
  #
73
- # class ApplicationController < ActionController::Base
74
- # def self.default_url_options
75
- # { :locale => I18n.locale }
72
+ # class ApplicationController < ActionController::Base
73
+ # def self.default_url_options
74
+ # { :locale => I18n.locale }
75
+ # end
76
76
  # end
77
- # end
78
77
  #
79
78
  # * :controllers => the controller which should be used. All routes by default points to Devise controllers.
80
79
  # However, if you want them to point to custom controller, you should do:
81
80
  #
82
- # devise_for :users, :controllers => { :sessions => "users/sessions" }
81
+ # devise_for :users, :controllers => { :sessions => "users/sessions" }
83
82
  #
84
83
  # * :skip => tell which controller you want to skip routes from being created:
85
84
  #
86
- # devise_for :users, :skip => :sessions
85
+ # devise_for :users, :skip => :sessions
87
86
  #
88
87
  def devise_for(*resources)
89
88
  options = resources.extract_options!
@@ -110,7 +109,7 @@ module ActionDispatch::Routing
110
109
  protected
111
110
 
112
111
  def devise_session(mapping, controllers)
113
- scope mapping.path do
112
+ scope mapping.full_path do
114
113
  get mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#new", :as => :"new_#{mapping.name}_session"
115
114
  post mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#create", :as => :"#{mapping.name}_session"
116
115
  get mapping.path_names[:sign_out], :to => "#{controllers[:sessions]}#destroy", :as => :"destroy_#{mapping.name}_session"
@@ -118,26 +117,26 @@ module ActionDispatch::Routing
118
117
  end
119
118
 
120
119
  def devise_password(mapping, controllers)
121
- scope mapping.path, :name_prefix => mapping.name do
122
- resource :password, :only => [:new, :create, :edit, :update], :as => mapping.path_names[:password], :controller => controllers[:passwords]
120
+ scope mapping.full_path, :name_prefix => mapping.name do
121
+ resource :password, :only => [:new, :create, :edit, :update], :path => mapping.path_names[:password], :controller => controllers[:passwords]
123
122
  end
124
123
  end
125
124
 
126
125
  def devise_confirmation(mapping, controllers)
127
- scope mapping.path, :name_prefix => mapping.name do
128
- resource :confirmation, :only => [:new, :create, :show], :as => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
126
+ scope mapping.full_path, :name_prefix => mapping.name do
127
+ resource :confirmation, :only => [:new, :create, :show], :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
129
128
  end
130
129
  end
131
130
 
132
131
  def devise_unlock(mapping, controllers)
133
- scope mapping.path, :name_prefix => mapping.name do
134
- resource :unlock, :only => [:new, :create, :show], :as => mapping.path_names[:unlock], :controller => controllers[:unlocks]
132
+ scope mapping.full_path, :name_prefix => mapping.name do
133
+ resource :unlock, :only => [:new, :create, :show], :path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
135
134
  end
136
135
  end
137
136
 
138
137
  def devise_registration(mapping, controllers)
139
- scope mapping.path[1..-1], :name_prefix => "#{mapping.name}_registration" do
140
- resource :registration, :only => [:new, :create, :edit, :update, :destroy], :as => "",
138
+ scope mapping.full_path[1..-1], :name_prefix => mapping.name do
139
+ resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => "",
141
140
  :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
142
141
  end
143
142
  end