devise 1.0.10 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. data/CHANGELOG.rdoc +62 -10
  2. data/Gemfile +23 -0
  3. data/Gemfile.lock +118 -0
  4. data/README.rdoc +116 -77
  5. data/Rakefile +4 -2
  6. data/TODO +3 -2
  7. data/app/controllers/{confirmations_controller.rb → devise/confirmations_controller.rb} +1 -1
  8. data/app/controllers/{passwords_controller.rb → devise/passwords_controller.rb} +1 -1
  9. data/app/controllers/{registrations_controller.rb → devise/registrations_controller.rb} +12 -8
  10. data/app/controllers/devise/sessions_controller.rb +23 -0
  11. data/app/controllers/{unlocks_controller.rb → devise/unlocks_controller.rb} +1 -8
  12. data/app/helpers/devise_helper.rb +17 -0
  13. data/app/mailers/devise/mailer.rb +71 -0
  14. data/app/views/devise/confirmations/new.html.erb +12 -0
  15. data/app/views/devise/passwords/edit.html.erb +16 -0
  16. data/app/views/devise/passwords/new.html.erb +12 -0
  17. data/app/views/devise/registrations/edit.html.erb +25 -0
  18. data/app/views/devise/registrations/new.html.erb +18 -0
  19. data/app/views/devise/sessions/new.html.erb +17 -0
  20. data/app/views/devise/shared/_links.erb +19 -0
  21. data/app/views/devise/unlocks/new.html.erb +12 -0
  22. data/{lib/devise → config}/locales/en.yml +16 -12
  23. data/lib/devise/controllers/helpers.rb +57 -52
  24. data/lib/devise/controllers/internal_helpers.rb +19 -50
  25. data/lib/devise/controllers/scoped_views.rb +35 -0
  26. data/lib/devise/controllers/url_helpers.rb +1 -1
  27. data/lib/devise/encryptors/authlogic_sha512.rb +0 -2
  28. data/lib/devise/encryptors/base.rb +1 -1
  29. data/lib/devise/encryptors/bcrypt.rb +2 -4
  30. data/lib/devise/encryptors/clearance_sha1.rb +0 -2
  31. data/lib/devise/encryptors/sha1.rb +6 -8
  32. data/lib/devise/encryptors/sha512.rb +6 -8
  33. data/lib/devise/failure_app.rb +76 -39
  34. data/lib/devise/hooks/activatable.rb +6 -10
  35. data/lib/devise/hooks/forgetable.rb +11 -0
  36. data/lib/devise/hooks/rememberable.rb +40 -30
  37. data/lib/devise/hooks/timeoutable.rb +7 -3
  38. data/lib/devise/hooks/trackable.rb +5 -14
  39. data/lib/devise/mapping.rb +35 -62
  40. data/lib/devise/models/authenticatable.rb +126 -0
  41. data/lib/devise/models/confirmable.rb +19 -22
  42. data/lib/devise/models/database_authenticatable.rb +26 -60
  43. data/lib/devise/models/lockable.rb +43 -28
  44. data/lib/devise/models/recoverable.rb +11 -10
  45. data/lib/devise/models/rememberable.rb +56 -26
  46. data/lib/devise/models/timeoutable.rb +1 -3
  47. data/lib/devise/models/token_authenticatable.rb +14 -43
  48. data/lib/devise/models/trackable.rb +14 -0
  49. data/lib/devise/models/validatable.rb +16 -2
  50. data/lib/devise/models.rb +16 -53
  51. data/lib/devise/modules.rb +23 -0
  52. data/lib/devise/orm/active_record.rb +10 -15
  53. data/lib/devise/orm/mongoid.rb +29 -0
  54. data/lib/devise/path_checker.rb +18 -0
  55. data/lib/devise/rails/routes.rb +232 -117
  56. data/lib/devise/rails/warden_compat.rb +18 -39
  57. data/lib/devise/rails.rb +64 -9
  58. data/lib/devise/schema.rb +47 -23
  59. data/lib/devise/strategies/authenticatable.rb +123 -0
  60. data/lib/devise/strategies/base.rb +2 -3
  61. data/lib/devise/strategies/database_authenticatable.rb +7 -22
  62. data/lib/devise/strategies/rememberable.rb +21 -7
  63. data/lib/devise/strategies/token_authenticatable.rb +31 -19
  64. data/lib/devise/test_helpers.rb +6 -6
  65. data/lib/devise/version.rb +1 -1
  66. data/lib/devise.rb +174 -157
  67. data/lib/generators/active_record/devise_generator.rb +28 -0
  68. data/{generators/devise → lib/generators/active_record}/templates/migration.rb +9 -3
  69. data/lib/generators/devise/devise_generator.rb +17 -0
  70. data/lib/generators/devise/install_generator.rb +24 -0
  71. data/lib/generators/devise/orm_helpers.rb +23 -0
  72. data/{generators/devise_install → lib/generators/devise}/templates/README +9 -7
  73. data/lib/generators/devise/templates/devise.rb +142 -0
  74. data/lib/generators/devise/views_generator.rb +63 -0
  75. data/lib/generators/devise_install_generator.rb +4 -0
  76. data/lib/generators/devise_views_generator.rb +4 -0
  77. data/lib/generators/mongoid/devise_generator.rb +17 -0
  78. data/test/controllers/helpers_test.rb +48 -19
  79. data/test/controllers/internal_helpers_test.rb +12 -16
  80. data/test/controllers/url_helpers_test.rb +21 -10
  81. data/test/devise_test.rb +16 -25
  82. data/test/encryptors_test.rb +2 -3
  83. data/test/failure_app_test.rb +106 -27
  84. data/test/integration/authenticatable_test.rb +138 -126
  85. data/test/integration/confirmable_test.rb +22 -15
  86. data/test/integration/database_authenticatable_test.rb +38 -0
  87. data/test/integration/http_authenticatable_test.rb +9 -12
  88. data/test/integration/lockable_test.rb +22 -15
  89. data/test/integration/recoverable_test.rb +6 -6
  90. data/test/integration/registerable_test.rb +42 -33
  91. data/test/integration/rememberable_test.rb +84 -22
  92. data/test/integration/timeoutable_test.rb +16 -4
  93. data/test/integration/token_authenticatable_test.rb +45 -12
  94. data/test/integration/trackable_test.rb +1 -1
  95. data/test/mailers/confirmation_instructions_test.rb +11 -17
  96. data/test/mailers/reset_password_instructions_test.rb +7 -7
  97. data/test/mailers/unlock_instructions_test.rb +7 -7
  98. data/test/mapping_test.rb +22 -95
  99. data/test/models/confirmable_test.rb +12 -19
  100. data/test/models/{authenticatable_test.rb → database_authenticatable_test.rb} +24 -56
  101. data/test/models/lockable_test.rb +32 -46
  102. data/test/models/recoverable_test.rb +7 -7
  103. data/test/models/rememberable_test.rb +118 -35
  104. data/test/models/timeoutable_test.rb +1 -1
  105. data/test/models/token_authenticatable_test.rb +5 -19
  106. data/test/models/trackable_test.rb +1 -1
  107. data/test/models/validatable_test.rb +20 -27
  108. data/test/models_test.rb +12 -5
  109. data/test/orm/active_record.rb +1 -23
  110. data/test/orm/mongoid.rb +10 -0
  111. data/test/rails_app/app/active_record/admin.rb +1 -5
  112. data/test/rails_app/app/active_record/shim.rb +2 -0
  113. data/test/rails_app/app/active_record/user.rb +3 -3
  114. data/test/rails_app/app/controllers/application_controller.rb +2 -5
  115. data/test/rails_app/app/controllers/home_controller.rb +3 -0
  116. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
  117. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
  118. data/test/rails_app/app/controllers/sessions_controller.rb +6 -0
  119. data/test/rails_app/app/controllers/users_controller.rb +7 -5
  120. data/test/rails_app/app/mongoid/admin.rb +6 -0
  121. data/test/rails_app/app/mongoid/shim.rb +16 -0
  122. data/test/rails_app/app/mongoid/user.rb +10 -0
  123. data/test/rails_app/config/application.rb +35 -0
  124. data/test/rails_app/config/boot.rb +10 -107
  125. data/test/rails_app/config/environment.rb +4 -41
  126. data/test/rails_app/config/environments/development.rb +15 -13
  127. data/test/rails_app/config/environments/production.rb +25 -20
  128. data/test/rails_app/config/environments/test.rb +33 -28
  129. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  130. data/test/rails_app/config/initializers/devise.rb +95 -38
  131. data/test/rails_app/config/initializers/secret_token.rb +2 -0
  132. data/test/rails_app/config/routes.rb +47 -25
  133. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +27 -0
  134. data/test/rails_app/db/schema.rb +86 -0
  135. data/test/routes_test.rb +62 -47
  136. data/test/support/{assertions_helper.rb → assertions.rb} +2 -15
  137. data/test/support/{tests_helper.rb → helpers.rb} +18 -3
  138. data/test/support/{integration_tests_helper.rb → integration.rb} +24 -7
  139. data/test/support/webrat/integrations/rails.rb +32 -0
  140. data/test/test_helper.rb +11 -11
  141. data/test/test_helpers_test.rb +30 -15
  142. metadata +105 -64
  143. data/app/controllers/sessions_controller.rb +0 -42
  144. data/app/models/devise_mailer.rb +0 -68
  145. data/app/views/confirmations/new.html.erb +0 -12
  146. data/app/views/passwords/edit.html.erb +0 -16
  147. data/app/views/passwords/new.html.erb +0 -12
  148. data/app/views/registrations/edit.html.erb +0 -25
  149. data/app/views/registrations/new.html.erb +0 -17
  150. data/app/views/sessions/new.html.erb +0 -17
  151. data/app/views/shared/_devise_links.erb +0 -19
  152. data/app/views/unlocks/new.html.erb +0 -12
  153. data/generators/devise/USAGE +0 -5
  154. data/generators/devise/devise_generator.rb +0 -15
  155. data/generators/devise/lib/route_devise.rb +0 -32
  156. data/generators/devise/templates/model.rb +0 -9
  157. data/generators/devise_install/USAGE +0 -3
  158. data/generators/devise_install/devise_install_generator.rb +0 -15
  159. data/generators/devise_install/templates/devise.rb +0 -105
  160. data/generators/devise_views/USAGE +0 -3
  161. data/generators/devise_views/devise_views_generator.rb +0 -21
  162. data/lib/devise/models/activatable.rb +0 -16
  163. data/lib/devise/models/http_authenticatable.rb +0 -23
  164. data/lib/devise/orm/data_mapper.rb +0 -83
  165. data/lib/devise/orm/mongo_mapper.rb +0 -52
  166. data/lib/devise/strategies/http_authenticatable.rb +0 -59
  167. data/rails/init.rb +0 -2
  168. data/test/integration/rack_middleware_test.rb +0 -47
  169. data/test/orm/mongo_mapper.rb +0 -20
  170. data/test/rails_app/app/mongo_mapper/admin.rb +0 -13
  171. data/test/rails_app/app/mongo_mapper/user.rb +0 -14
  172. data/test/rails_app/config/initializers/new_rails_defaults.rb +0 -24
  173. data/test/rails_app/config/initializers/session_store.rb +0 -15
  174. /data/app/views/{devise_mailer → devise/mailer}/confirmation_instructions.html.erb +0 -0
  175. /data/app/views/{devise_mailer → devise/mailer}/reset_password_instructions.html.erb +0 -0
  176. /data/app/views/{devise_mailer → devise/mailer}/unlock_instructions.html.erb +0 -0
@@ -1,133 +1,248 @@
1
- module ActionController::Routing
1
+ module ActionDispatch::Routing
2
2
  class RouteSet #:nodoc:
3
-
4
3
  # Ensure Devise modules are included only after loading routes, because we
5
- # need devise_for mappings already declared to create magic filters and
6
- # helpers.
7
- def load_routes_with_devise!
8
- load_routes_without_devise!
9
- return if Devise.mappings.empty?
10
-
4
+ # need devise_for mappings already declared to create filters and helpers.
5
+ def finalize_with_devise!
6
+ finalize_without_devise!
7
+ Devise.configure_warden!
11
8
  ActionController::Base.send :include, Devise::Controllers::Helpers
12
- ActionController::Base.send :include, Devise::Controllers::UrlHelpers
13
-
14
- ActionView::Base.send :include, Devise::Controllers::UrlHelpers
15
9
  end
16
- alias_method_chain :load_routes!, :devise
17
-
18
- class Mapper #:doc:
19
- # Includes devise_for method for routes. This method is responsible to
20
- # generate all needed routes for devise, based on what modules you have
21
- # defined in your model.
22
- # Examples: Let's say you have an User model configured to use
23
- # authenticatable, confirmable and recoverable modules. After creating this
24
- # inside your routes:
25
- #
26
- # map.devise_for :users
27
- #
28
- # this method is going to look inside your User model and create the
29
- # needed routes:
30
- #
31
- # # Session routes for Authenticatable (default)
32
- # new_user_session GET /users/sign_in {:controller=>"sessions", :action=>"new"}
33
- # user_session POST /users/sign_in {:controller=>"sessions", :action=>"create"}
34
- # destroy_user_session GET /users/sign_out {:controller=>"sessions", :action=>"destroy"}
35
- #
36
- # # Password routes for Recoverable, if User model has :recoverable configured
37
- # new_user_password GET /users/password/new(.:format) {:controller=>"passwords", :action=>"new"}
38
- # edit_user_password GET /users/password/edit(.:format) {:controller=>"passwords", :action=>"edit"}
39
- # user_password PUT /users/password(.:format) {:controller=>"passwords", :action=>"update"}
40
- # POST /users/password(.:format) {:controller=>"passwords", :action=>"create"}
41
- #
42
- # # Confirmation routes for Confirmable, if User model has :confirmable configured
43
- # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"confirmations", :action=>"new"}
44
- # user_confirmation GET /users/confirmation(.:format) {:controller=>"confirmations", :action=>"show"}
45
- # POST /users/confirmation(.:format) {:controller=>"confirmations", :action=>"create"}
46
- #
47
- # You can configure your routes with some options:
48
- #
49
- # * :class_name => setup a different class to be looked up by devise, if it cannot be correctly find by the route name.
50
- #
51
- # map.devise_for :users, :class_name => 'Account'
52
- #
53
- # * :as => allows you to setup path name that will be used, as rails routes does. The following route configuration would setup your route as /accounts instead of /users:
54
- #
55
- # map.devise_for :users, :as => 'accounts'
56
- #
57
- # * :scope => setup the scope name. This is used as the instance variable name in controller, as the name in routes and the scope given to warden. Defaults to the singular of the given name:
58
- #
59
- # map.devise_for :users, :scope => :account
60
- #
61
- # * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :password and :confirmation.
62
- #
63
- # map.devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
64
- #
65
- # * :path_prefix => the path prefix to be used in all routes.
66
- #
67
- # map.devise_for :users, :path_prefix => "/:locale"
68
- #
69
- # * :sign_out_via => restirct the HTTP method(s) accepted for the :sign_out action (default: :get), possible values are :post, :get, :put, :delete and :any, e.g. if you wish to restrict this to accept only :delete requests you should do:
70
- #
71
- # map.devise_for :users, :sign_out_via => :delete
72
- #
73
- # You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
74
- #
75
- # Any other options will be passed to route definition. If you need conditions for your routes, just map:
76
- #
77
- # map.devise_for :users, :conditions => { :subdomain => /.+/ }
78
- #
79
- # If you are using a dynamic prefix, like :locale above, you need to configure default_url_options through Devise. You can do that in config/initializers/devise.rb or setting a Devise.default_url_options:
80
- #
81
- # Devise.default_url_options do
82
- # { :locale => I18n.locale }
83
- # end
84
- #
85
- def devise_for(*resources)
86
- options = resources.extract_options!
87
-
88
- resources.map!(&:to_sym)
89
- resources.each do |resource|
90
- mapping = Devise::Mapping.new(resource, options.dup)
91
- Devise.default_scope ||= mapping.name
92
- Devise.mappings[mapping.name] = mapping
93
-
94
- route_options = mapping.route_options.merge(:path_prefix => mapping.raw_path, :name_prefix => "#{mapping.name}_")
95
-
96
- with_options(route_options) do |routes|
97
- mapping.for.each do |mod|
98
- send(mod, routes, mapping) if self.respond_to?(mod, true)
99
- end
100
- end
101
- end
10
+ alias_method_chain :finalize!, :devise
11
+ end
12
+
13
+ class Mapper
14
+ # Includes devise_for method for routes. This method is responsible to
15
+ # generate all needed routes for devise, based on what modules you have
16
+ # defined in your model.
17
+ #
18
+ # ==== Examples
19
+ #
20
+ # Let's say you have an User model configured to use authenticatable,
21
+ # confirmable and recoverable modules. After creating this inside your routes:
22
+ #
23
+ # devise_for :users
24
+ #
25
+ # This method is going to look inside your User model and create the
26
+ # needed routes:
27
+ #
28
+ # # Session routes for Authenticatable (default)
29
+ # new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
30
+ # user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
31
+ # destroy_user_session GET /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
32
+ #
33
+ # # Password routes for Recoverable, if User model has :recoverable configured
34
+ # new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
35
+ # edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
36
+ # user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
37
+ # POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
38
+ #
39
+ # # Confirmation routes for Confirmable, if User model has :confirmable configured
40
+ # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
41
+ # user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
42
+ # POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
43
+ #
44
+ # ==== Options
45
+ #
46
+ # You can configure your routes with some options:
47
+ #
48
+ # * :class_name => setup a different class to be looked up by devise,
49
+ # if it cannot be correctly find by the route name.
50
+ #
51
+ # devise_for :users, :class_name => 'Account'
52
+ #
53
+ # * :path => allows you to setup path name that will be used, as rails routes does.
54
+ # The following route configuration would setup your route as /accounts instead of /users:
55
+ #
56
+ # devise_for :users, :path => 'accounts'
57
+ #
58
+ # * :singular => setup the singular name for the given resource. This is used as the instance variable name in
59
+ # controller, as the name in routes and the scope given to warden.
60
+ #
61
+ # devise_for :users, :singular => :user
62
+ #
63
+ # * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
64
+ # :password, :confirmation, :unlock.
65
+ #
66
+ # devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
67
+ #
68
+ # * :controllers => the controller which should be used. All routes by default points to Devise controllers.
69
+ # However, if you want them to point to custom controller, you should do:
70
+ #
71
+ # devise_for :users, :controllers => { :sessions => "users/sessions" }
72
+ #
73
+ # * :module => the namespace to find controlers. By default, devise will access devise/sessions,
74
+ # devise/registrations and so on. If you want to namespace all at once, use module:
75
+ #
76
+ # devise_for :users, :module => "users"
77
+ #
78
+ # Notice that whenever you use namespace in the router DSL, it automatically sets the module.
79
+ # So the following setup:
80
+ #
81
+ # namespace :publisher
82
+ # devise_for :account
83
+ # end
84
+ #
85
+ # Will use publisher/sessions controller instead of devise/sessions controller. You can revert
86
+ # this by providing the :module option to devise_for.
87
+ #
88
+ # * :skip => tell which controller you want to skip routes from being created:
89
+ #
90
+ # devise_for :users, :skip => :sessions
91
+ #
92
+ # ==== Scoping
93
+ #
94
+ # Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
95
+ #
96
+ # scope "/my" do
97
+ # devise_for :users
98
+ # end
99
+ #
100
+ # However, since Devise uses the request path to retrieve the current user, it has one caveats.
101
+ # If you are using a dynamic segment, as below:
102
+ #
103
+ # scope ":locale" do
104
+ # devise_for :users
105
+ # end
106
+ #
107
+ # You are required to configure default_url_options in your ApplicationController class level, so
108
+ # Devise can pick it:
109
+ #
110
+ # class ApplicationController < ActionController::Base
111
+ # def self.default_url_options
112
+ # { :locale => I18n.locale }
113
+ # end
114
+ # end
115
+ #
116
+ def devise_for(*resources)
117
+ options = resources.extract_options!
118
+
119
+ if as = options.delete(:as)
120
+ ActiveSupport::Deprecation.warn ":as is deprecated, please use :path instead."
121
+ options[:path] ||= as
102
122
  end
103
123
 
104
- protected
124
+ if scope = options.delete(:scope)
125
+ ActiveSupport::Deprecation.warn ":scope is deprecated, please use :singular instead."
126
+ options[:singular] ||= scope
127
+ end
105
128
 
106
- def database_authenticatable(routes, mapping)
107
- routes.with_options(:controller => 'sessions', :name_prefix => nil) do |session|
108
- session.send(:"new_#{mapping.name}_session", mapping.path_names[:sign_in], :action => 'new', :conditions => { :method => :get })
109
- session.send(:"#{mapping.name}_session", mapping.path_names[:sign_in], :action => 'create', :conditions => { :method => :post })
110
- destroy_options = { :action => 'destroy' }
111
- destroy_options.merge! :conditions => { :method => mapping.sign_out_via } unless mapping.sign_out_via == :any
112
- session.send(:"destroy_#{mapping.name}_session", mapping.path_names[:sign_out], destroy_options)
113
- end
114
- end
129
+ options[:as] ||= @scope[:as] if @scope[:as].present?
130
+ options[:module] ||= @scope[:module] if @scope[:module].present?
131
+ options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
132
+ options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
115
133
 
116
- def confirmable(routes, mapping)
117
- routes.resource :confirmation, :only => [:new, :create, :show], :as => mapping.path_names[:confirmation]
118
- end
134
+ resources.map!(&:to_sym)
119
135
 
120
- def lockable(routes, mapping)
121
- routes.resource :unlock, :only => [:new, :create, :show], :as => mapping.path_names[:unlock]
122
- end
136
+ resources.each do |resource|
137
+ mapping = Devise.add_mapping(resource, options)
123
138
 
124
- def recoverable(routes, mapping)
125
- routes.resource :password, :only => [:new, :create, :edit, :update], :as => mapping.path_names[:password]
139
+ begin
140
+ raise_no_devise_method_error!(mapping.class_name) unless mapping.to.respond_to?(:devise)
141
+ rescue NameError => e
142
+ raise unless mapping.class_name == resource.to_s.classify
143
+ warn "[WARNING] You provided devise_for #{resource.inspect} but there is " <<
144
+ "no model #{mapping.class_name} defined in your application"
145
+ next
146
+ rescue NoMethodError => e
147
+ raise unless e.message.include?("undefined method `devise'")
148
+ raise_no_devise_method_error!(mapping.class_name)
126
149
  end
127
150
 
128
- def registerable(routes, mapping)
129
- routes.resource :registration, :only => [:new, :create, :edit, :update, :destroy], :as => mapping.raw_path[1..-1], :path_prefix => nil, :path_names => { :new => mapping.path_names[:sign_up] }
151
+ routes = mapping.routes
152
+ routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
153
+
154
+ devise_scope mapping.name do
155
+ yield if block_given?
156
+ with_devise_exclusive_scope mapping.fullpath, mapping.name do
157
+ routes.each { |mod| send(:"devise_#{mod}", mapping, mapping.controllers) }
158
+ end
130
159
  end
160
+ end
161
+ end
162
+
163
+ # Allow you to add authentication request from the router:
164
+ #
165
+ # authenticate(:user) do
166
+ # resources :post
167
+ # end
168
+ #
169
+ def authenticate(scope)
170
+ constraint = lambda do |request|
171
+ request.env["warden"].authenticate!(:scope => scope)
172
+ end
173
+
174
+ constraints(constraint) do
175
+ yield
176
+ end
177
+ end
178
+
179
+ # Sets the devise scope to be used in the controller. If you have custom routes,
180
+ # you are required to call this method (also aliased as :as) in order to specify
181
+ # to which controller it is targetted.
182
+ #
183
+ # as :user do
184
+ # get "sign_in", :to => "devise/sessions#new"
185
+ # end
186
+ #
187
+ # Notice you cannot have two scopes mapping to the same URL. And remember, if
188
+ # you try to access a devise controller without specifying a scope, it will
189
+ # raise ActionNotFound error.
190
+ def devise_scope(scope)
191
+ constraint = lambda do |request|
192
+ request.env["devise.mapping"] = Devise.mappings[scope]
193
+ true
194
+ end
195
+
196
+ constraints(constraint) do
197
+ yield
198
+ end
131
199
  end
200
+ alias :as :devise_scope
201
+
202
+ protected
203
+
204
+ def devise_session(mapping, controllers) #:nodoc:
205
+ scope :controller => controllers[:sessions], :as => :session do
206
+ get :new, :path => mapping.path_names[:sign_in]
207
+ post :create, :path => mapping.path_names[:sign_in], :as => ""
208
+ get :destroy, :path => mapping.path_names[:sign_out]
209
+ end
210
+ end
211
+
212
+ def devise_password(mapping, controllers) #:nodoc:
213
+ resource :password, :only => [:new, :create, :edit, :update],
214
+ :path => mapping.path_names[:password], :controller => controllers[:passwords]
215
+ end
216
+
217
+ def devise_confirmation(mapping, controllers) #:nodoc:
218
+ resource :confirmation, :only => [:new, :create, :show],
219
+ :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
220
+ end
221
+
222
+ def devise_unlock(mapping, controllers) #:nodoc:
223
+ if mapping.to.unlock_strategy_enabled?(:email)
224
+ resource :unlock, :only => [:new, :create, :show],
225
+ :path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
226
+ end
227
+ end
228
+
229
+ def devise_registration(mapping, controllers) #:nodoc:
230
+ resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
231
+ :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
232
+ end
233
+
234
+ def with_devise_exclusive_scope(new_path, new_as) #:nodoc:
235
+ old_as, old_path, old_module = @scope[:as], @scope[:path], @scope[:module]
236
+ @scope[:as], @scope[:path], @scope[:module] = new_as, new_path, nil
237
+ yield
238
+ ensure
239
+ @scope[:as], @scope[:path], @scope[:module] = old_as, old_path, old_module
240
+ end
241
+
242
+ def raise_no_devise_method_error!(klass) #:nodoc:
243
+ raise "#{klass} does not respond to 'devise' method. This usually means you haven't " <<
244
+ "loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
245
+ "inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
246
+ end
132
247
  end
133
248
  end
@@ -1,6 +1,6 @@
1
1
  module Warden::Mixins::Common
2
2
  def request
3
- @request ||= env['action_controller.rescue.request']
3
+ @request ||= ActionDispatch::Request.new(env)
4
4
  end
5
5
 
6
6
  def reset_session!
@@ -8,53 +8,32 @@ module Warden::Mixins::Common
8
8
  raw_session.clear
9
9
  end
10
10
 
11
- def response
12
- @response ||= env['action_controller.rescue.response']
11
+ def cookies
12
+ request.cookie_jar
13
13
  end
14
14
  end
15
15
 
16
16
  class Warden::SessionSerializer
17
17
  def serialize(record)
18
- [record.class, record.id]
18
+ [record.class.name, record.id]
19
19
  end
20
20
 
21
21
  def deserialize(keys)
22
22
  klass, id = keys
23
- klass.find(:first, :conditions => { :id => id })
24
- end
25
- end
26
-
27
- class ActionController::Request
28
- def reset_session
29
- session.destroy if session && session.respond_to?(:destroy)
30
- self.session = {}
31
- end
32
- end
33
-
34
- # Solve a bug in Rails where Set-Cookie is returning an array.
35
- class Devise::CookieSanitizer
36
- SET_COOKIE = "Set-Cookie".freeze
37
-
38
- def initialize(app)
39
- @app = app
40
- end
41
-
42
- def call(env)
43
- response = @app.call(env)
44
- headers = response[1]
45
- headers[SET_COOKIE] = headers[SET_COOKIE].join("\n") if headers[SET_COOKIE].respond_to?(:join)
46
- response
47
- end
48
- end
49
-
50
- Rails.configuration.middleware.insert_after ActionController::Failsafe, Devise::CookieSanitizer
51
23
 
52
- Warden::Manager.after_set_user :event => [:set_user, :authentication] do |record, warden, options|
53
- if options[:scope] && warden.authenticated?(options[:scope])
54
- request = warden.request
55
- backup = request.session.to_hash
56
- backup.delete(:session_id)
57
- request.reset_session
58
- request.session.update(backup)
24
+ if klass.is_a?(Class)
25
+ raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
26
+ "you can fix it by changing one character in your cookie secret, forcing all previous " <<
27
+ "cookies to expire, or cleaning up your database sessions if you are using a db store."
28
+ end
29
+
30
+ klass.constantize.find(:first, :conditions => { :id => id })
31
+ rescue NameError => e
32
+ if e.message =~ /uninitialized constant/
33
+ Rails.logger.debug "Trying to deserialize invalid class #{klass}"
34
+ nil
35
+ else
36
+ raise
37
+ end
59
38
  end
60
39
  end
data/lib/devise/rails.rb CHANGED
@@ -1,14 +1,69 @@
1
1
  require 'devise/rails/routes'
2
2
  require 'devise/rails/warden_compat'
3
3
 
4
- Rails.configuration.after_initialize do
5
- require "devise/orm/#{Devise.orm}"
4
+ # Include UrlHelpers in ActionController and ActionView as soon as they are loaded.
5
+ ActiveSupport.on_load(:action_controller) { include Devise::Controllers::UrlHelpers }
6
+ ActiveSupport.on_load(:action_view) { include Devise::Controllers::UrlHelpers }
6
7
 
7
- # Adds Warden Manager to Rails middleware stack, configuring default devise
8
- # strategy and also the failure app.
9
- Rails.configuration.middleware.use Warden::Manager do |config|
10
- Devise.configure_warden(config)
11
- end
8
+ module Devise
9
+ class Engine < ::Rails::Engine
10
+ config.devise = Devise
11
+
12
+ config.app_middleware.use Warden::Manager do |config|
13
+ Devise.warden_config = config
14
+ end
15
+
16
+ # Force routes to be loaded if we are doing any eager load.
17
+ config.before_eager_load { |app| app.reload_routes! }
18
+
19
+ config.after_initialize do
20
+ Devise.encryptor ||= begin
21
+ warn "[WARNING] config.encryptor is not set in your config/initializers/devise.rb. " \
22
+ "Devise will then set it to :bcrypt. If you were using the previous default " \
23
+ "encryptor, please add config.encryptor = :sha1 to your configuration file." if Devise.mailer_sender
24
+ :bcrypt
25
+ end
26
+ end
27
+
28
+ initializer "devise.add_filters" do |app|
29
+ app.config.filter_parameters += [:password, :password_confirmation]
30
+ app.config.filter_parameters.uniq
31
+ end
32
+
33
+ unless Rails.env.production?
34
+ config.after_initialize do
35
+ actions = [:confirmation_instructions, :reset_password_instructions, :unlock_instructions]
36
+
37
+ translations = begin
38
+ I18n.t("devise.mailer", :raise => true).map { |k, v| k if v.is_a?(String) }.compact
39
+ rescue Exception => e # Do not care if something fails
40
+ []
41
+ end
12
42
 
13
- I18n.load_path.unshift File.expand_path(File.join(File.dirname(__FILE__), 'locales', 'en.yml'))
14
- end
43
+ keys = actions & translations
44
+
45
+ keys.each do |key|
46
+ ActiveSupport::Deprecation.warn "The I18n message 'devise.mailer.#{key}' is deprecated. " \
47
+ "Please use 'devise.mailer.#{key}.subject' instead."
48
+ end
49
+ end
50
+
51
+ config.after_initialize do
52
+ flash = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked]
53
+
54
+ translations = begin
55
+ I18n.t("devise.sessions", :raise => true).keys
56
+ rescue Exception => e # Do not care if something fails
57
+ []
58
+ end
59
+
60
+ keys = flash & translations
61
+
62
+ if keys.any?
63
+ ActiveSupport::Deprecation.warn "The following I18n messages in 'devise.sessions' " \
64
+ "are deprecated: #{keys.to_sentence}. Please move them to 'devise.failure' instead."
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/devise/schema.rb CHANGED
@@ -12,6 +12,11 @@ module Devise
12
12
  #
13
13
  # == Options
14
14
  # * :null - When true, allow columns to be null.
15
+ # * :default - Should be set to "" when :null is false.
16
+ #
17
+ # == Notes
18
+ # For Datamapper compatibility, we explicitly hardcode the limit for the
19
+ # encrypter password field in 128 characters.
15
20
  def database_authenticatable(options={})
16
21
  null = options[:null] || false
17
22
  default = options[:default] || ""
@@ -20,53 +25,72 @@ module Devise
20
25
  ActiveSupport::Deprecation.warn ":encryptor as option is deprecated, simply remove it."
21
26
  end
22
27
 
23
- apply_schema :email, String, :null => null, :default => default
24
- apply_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
25
- apply_schema :password_salt, String, :null => null, :default => default
26
- end
28
+ apply_devise_schema :email, String, :null => null, :default => default
29
+ apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
30
+ apply_devise_schema :password_salt, String, :null => null, :default => default
31
+ end
27
32
 
28
33
  # Creates authentication_token.
29
- def token_authenticatable
30
- apply_schema :authentication_token, String
34
+ def token_authenticatable(options={})
35
+ apply_devise_schema :authentication_token, String
31
36
  end
32
37
 
33
38
  # Creates confirmation_token, confirmed_at and confirmation_sent_at.
34
39
  def confirmable
35
- apply_schema :confirmation_token, String
36
- apply_schema :confirmed_at, DateTime
37
- apply_schema :confirmation_sent_at, DateTime
40
+ apply_devise_schema :confirmation_token, String
41
+ apply_devise_schema :confirmed_at, DateTime
42
+ apply_devise_schema :confirmation_sent_at, DateTime
38
43
  end
39
44
 
40
45
  # Creates reset_password_token.
41
46
  def recoverable
42
- apply_schema :reset_password_token, String
47
+ apply_devise_schema :reset_password_token, String
43
48
  end
44
49
 
45
50
  # Creates remember_token and remember_created_at.
46
51
  def rememberable
47
- apply_schema :remember_token, String
48
- apply_schema :remember_created_at, DateTime
52
+ apply_devise_schema :remember_token, String
53
+ apply_devise_schema :remember_created_at, DateTime
49
54
  end
50
55
 
51
56
  # Creates sign_in_count, current_sign_in_at, last_sign_in_at,
52
57
  # current_sign_in_ip, last_sign_in_ip.
53
58
  def trackable
54
- apply_schema :sign_in_count, Integer, :default => 0
55
- apply_schema :current_sign_in_at, DateTime
56
- apply_schema :last_sign_in_at, DateTime
57
- apply_schema :current_sign_in_ip, String
58
- apply_schema :last_sign_in_ip, String
59
+ apply_devise_schema :sign_in_count, Integer, :default => 0
60
+ apply_devise_schema :current_sign_in_at, DateTime
61
+ apply_devise_schema :last_sign_in_at, DateTime
62
+ apply_devise_schema :current_sign_in_ip, String
63
+ apply_devise_schema :last_sign_in_ip, String
59
64
  end
60
65
 
61
- # Creates failed_attempts, unlock_token and locked_at
62
- def lockable
63
- apply_schema :failed_attempts, Integer, :default => 0
64
- apply_schema :unlock_token, String
65
- apply_schema :locked_at, DateTime
66
+ # Creates failed_attempts, unlock_token and locked_at depending on the options given.
67
+ #
68
+ # == Options
69
+ # * :unlock_strategy - The strategy used for unlock. Can be :time, :email, :both (default), :none.
70
+ # If :email or :both, creates a unlock_token field.
71
+ # * :lock_strategy - The strategy used for locking. Can be :failed_attempts (default) or :none.
72
+ def lockable(options={})
73
+ unlock_strategy = options[:unlock_strategy]
74
+ unlock_strategy ||= self.unlock_strategy if respond_to?(:unlock_strategy)
75
+ unlock_strategy ||= :both
76
+
77
+ lock_strategy = options[:lock_strategy]
78
+ lock_strategy ||= self.lock_strategy if respond_to?(:lock_strategy)
79
+ lock_strategy ||= :failed_attempts
80
+
81
+ if lock_strategy == :failed_attempts
82
+ apply_devise_schema :failed_attempts, Integer, :default => 0
83
+ end
84
+
85
+ if [:both, :email].include?(unlock_strategy)
86
+ apply_devise_schema :unlock_token, String
87
+ end
88
+
89
+ apply_devise_schema :locked_at, DateTime
66
90
  end
67
91
 
68
92
  # Overwrite with specific modification to create your own schema.
69
- def apply_schema(name, type, options={})
93
+ def apply_devise_schema(name, type, options={})
70
94
  raise NotImplementedError
71
95
  end
72
96
  end