devise 2.1.4 → 2.2.0.rc

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 (84) hide show
  1. data/.travis.yml +26 -0
  2. data/CHANGELOG.rdoc +29 -10
  3. data/CONTRIBUTING.md +14 -0
  4. data/Gemfile +2 -8
  5. data/Gemfile.lock +68 -77
  6. data/README.md +15 -9
  7. data/app/controllers/devise/omniauth_callbacks_controller.rb +1 -1
  8. data/app/controllers/devise/passwords_controller.rb +9 -0
  9. data/app/controllers/devise/registrations_controller.rb +17 -5
  10. data/app/controllers/devise/sessions_controller.rb +3 -3
  11. data/app/controllers/devise_controller.rb +3 -11
  12. data/app/views/devise/confirmations/new.html.erb +1 -1
  13. data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
  14. data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
  15. data/app/views/devise/passwords/edit.html.erb +1 -1
  16. data/app/views/devise/passwords/new.html.erb +1 -1
  17. data/app/views/devise/registrations/edit.html.erb +5 -1
  18. data/app/views/devise/registrations/new.html.erb +1 -1
  19. data/app/views/devise/sessions/new.html.erb +1 -1
  20. data/app/views/devise/unlocks/new.html.erb +1 -1
  21. data/config/locales/en.yml +2 -0
  22. data/gemfiles/Gemfile.rails-3.1.x +1 -3
  23. data/gemfiles/Gemfile.rails-3.1.x.lock +9 -12
  24. data/lib/devise.rb +12 -7
  25. data/lib/devise/controllers/helpers.rb +16 -3
  26. data/lib/devise/mailers/helpers.rb +14 -8
  27. data/lib/devise/models/authenticatable.rb +14 -9
  28. data/lib/devise/models/confirmable.rb +36 -3
  29. data/lib/devise/models/database_authenticatable.rb +2 -1
  30. data/lib/devise/models/lockable.rb +6 -2
  31. data/lib/devise/models/recoverable.rb +2 -2
  32. data/lib/devise/models/token_authenticatable.rb +12 -0
  33. data/lib/devise/models/trackable.rb +1 -1
  34. data/lib/devise/models/validatable.rb +1 -1
  35. data/lib/devise/param_filter.rb +2 -1
  36. data/lib/devise/rails/routes.rb +11 -11
  37. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  38. data/lib/devise/test_helpers.rb +3 -2
  39. data/lib/devise/time_inflector.rb +14 -0
  40. data/lib/devise/version.rb +1 -1
  41. data/lib/generators/active_record/devise_generator.rb +5 -1
  42. data/lib/generators/mongoid/devise_generator.rb +0 -3
  43. data/lib/generators/templates/README +5 -1
  44. data/lib/generators/templates/devise.rb +12 -4
  45. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  46. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  47. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +2 -1
  48. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  49. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +1 -1
  50. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +5 -0
  51. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -1
  52. data/test/controllers/internal_helpers_test.rb +6 -0
  53. data/test/controllers/sessions_controller_test.rb +43 -1
  54. data/test/devise_test.rb +12 -1
  55. data/test/generators/active_record_generator_test.rb +7 -1
  56. data/test/integration/authenticatable_test.rb +4 -4
  57. data/test/integration/confirmable_test.rb +44 -0
  58. data/test/integration/database_authenticatable_test.rb +17 -15
  59. data/test/integration/http_authenticatable_test.rb +3 -3
  60. data/test/integration/lockable_test.rb +18 -0
  61. data/test/integration/omniauthable_test.rb +2 -2
  62. data/test/integration/recoverable_test.rb +43 -6
  63. data/test/integration/registerable_test.rb +34 -11
  64. data/test/mailers/confirmation_instructions_test.rb +7 -0
  65. data/test/models/authenticatable_test.rb +1 -7
  66. data/test/models/confirmable_test.rb +35 -1
  67. data/test/models/database_authenticatable_test.rb +49 -24
  68. data/test/models/lockable_test.rb +13 -3
  69. data/test/models/serializable_test.rb +2 -1
  70. data/test/models_test.rb +1 -22
  71. data/test/orm/mongoid.rb +2 -3
  72. data/test/rails_app/app/controllers/application_controller.rb +1 -0
  73. data/test/rails_app/app/mailers/users/mailer.rb +6 -1
  74. data/test/rails_app/app/mongoid/admin.rb +4 -2
  75. data/test/rails_app/app/mongoid/shim.rb +3 -3
  76. data/test/rails_app/app/mongoid/user.rb +2 -2
  77. data/test/rails_app/config/initializers/devise.rb +2 -2
  78. data/test/rails_app/lib/shared_user.rb +1 -1
  79. data/test/support/helpers.rb +2 -2
  80. data/test/support/integration.rb +4 -3
  81. data/test/test_helpers_test.rb +19 -2
  82. data/test/test_models.rb +27 -0
  83. metadata +31 -29
  84. data/test/indifferent_hash.rb +0 -33
@@ -64,6 +64,7 @@ module Devise
64
64
  result = if valid_password?(current_password)
65
65
  update_attributes(params, *options)
66
66
  else
67
+ params.delete(:password)
67
68
  self.assign_attributes(params, *options)
68
69
  self.valid?
69
70
  self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
@@ -75,7 +76,7 @@ module Devise
75
76
  end
76
77
 
77
78
  # Updates record attributes without asking for the current password.
78
- # Never allows to change the current password. If you are using this
79
+ # Never allows a change to the current password. If you are using this
79
80
  # method, you should probably override this method to protect other
80
81
  # attributes you would not like to be updated without a password.
81
82
  #
@@ -27,7 +27,7 @@ module Devise
27
27
  def self.required_fields(klass)
28
28
  attributes = []
29
29
  attributes << :failed_attempts if klass.lock_strategy_enabled?(:failed_attempts)
30
- attributes << :unlock_at if klass.unlock_strategy_enabled?(:time)
30
+ attributes << :locked_at if klass.unlock_strategy_enabled?(:time)
31
31
  attributes << :unlock_token if klass.unlock_strategy_enabled?(:email)
32
32
 
33
33
  attributes
@@ -105,7 +105,11 @@ module Devise
105
105
  end
106
106
 
107
107
  def unauthenticated_message
108
- if lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
108
+ # If set to paranoid mode, do not show the locked message because it
109
+ # leaks the existence of an account.
110
+ if Devise.paranoid
111
+ super
112
+ elsif lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
109
113
  :locked
110
114
  else
111
115
  super
@@ -102,9 +102,9 @@ module Devise
102
102
 
103
103
  module ClassMethods
104
104
  # Attempt to find a user by its email. If a record is found, send new
105
- # password instructions to it. If not user is found, returns a new user
105
+ # password instructions to it. If user is not found, returns a new user
106
106
  # with an email not found error.
107
- # Attributes must contain the user email
107
+ # Attributes must contain the user's email
108
108
  def send_reset_password_instructions(attributes={})
109
109
  recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
110
110
  recoverable.send_reset_password_instructions if recoverable.persisted?
@@ -18,6 +18,18 @@ module Devise
18
18
  # If you want to delete the token after it is used, you can do so in the
19
19
  # after_token_authentication callback.
20
20
  #
21
+ # == APIs
22
+ #
23
+ # If you are using token authentication with APIs and using trackable. Every
24
+ # request will be considered as a new sign in (since there is no session in
25
+ # APIs). You can disable this by creating a before filter as follow:
26
+ #
27
+ # before_filter :skip_trackable
28
+ #
29
+ # def skip_trackable
30
+ # request.env['devise.skip_trackable'] = true
31
+ # end
32
+ #
21
33
  # == Options
22
34
  #
23
35
  # TokenAuthenticatable adds the following options to devise_for:
@@ -20,7 +20,7 @@ module Devise
20
20
  self.last_sign_in_at = old_current || new_current
21
21
  self.current_sign_in_at = new_current
22
22
 
23
- old_current, new_current = self.current_sign_in_ip, request.ip
23
+ old_current, new_current = self.current_sign_in_ip, request.remote_ip
24
24
  self.last_sign_in_ip = old_current || new_current
25
25
  self.current_sign_in_ip = new_current
26
26
 
@@ -10,7 +10,7 @@ module Devise
10
10
  # Validatable adds the following options to devise_for:
11
11
  #
12
12
  # * +email_regexp+: the regular expression used to validate e-mails;
13
- # * +password_length+: a range expressing password length. Defaults to 6..128.
13
+ # * +password_length+: a range expressing password length. Defaults to 8..128.
14
14
  #
15
15
  module Validatable
16
16
  # All validations used by this module.
@@ -33,8 +33,9 @@ module Devise
33
33
 
34
34
  private
35
35
 
36
+ # Determine which values should be transformed to string or passed as-is to the query builder underneath
36
37
  def param_requires_string_conversion?(value)
37
- true
38
+ [Fixnum, TrueClass, FalseClass, Regexp].none? {|clz| value.is_a? clz }
38
39
  end
39
40
  end
40
41
  end
@@ -43,20 +43,20 @@ module ActionDispatch::Routing
43
43
  # needed routes:
44
44
  #
45
45
  # # Session routes for Authenticatable (default)
46
- # new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
47
- # user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
48
- # destroy_user_session GET /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
46
+ # new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
47
+ # user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
48
+ # destroy_user_session DELETE /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
49
49
  #
50
50
  # # Password routes for Recoverable, if User model has :recoverable configured
51
- # new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
52
- # edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
53
- # user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
54
- # POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
51
+ # new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
52
+ # edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
53
+ # user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
54
+ # POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
55
55
  #
56
56
  # # Confirmation routes for Confirmable, if User model has :confirmable configured
57
- # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
58
- # user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
59
- # POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
57
+ # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
58
+ # user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
59
+ # POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
60
60
  #
61
61
  # ==== Options
62
62
  #
@@ -183,7 +183,7 @@ module ActionDispatch::Routing
183
183
  # end
184
184
  # end
185
185
  #
186
- # In order to get Devise to recognize the deactivate action, your devise_for entry should look like this,
186
+ # In order to get Devise to recognize the deactivate action, your devise_scope entry should look like this:
187
187
  #
188
188
  # devise_scope :owner do
189
189
  # post "deactivate", :to => "registrations#deactivate", :as => "deactivate_registration"
@@ -6,7 +6,7 @@ module Devise
6
6
  class DatabaseAuthenticatable < Authenticatable
7
7
  def authenticate!
8
8
  resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
9
- return fail(:invalid) unless resource
9
+ return fail(:not_found_in_database) unless resource
10
10
 
11
11
  if validate(resource){ resource.valid_password?(password) }
12
12
  resource.after_database_authentication
@@ -45,6 +45,7 @@ module Devise
45
45
  def sign_in(resource_or_scope, resource=nil)
46
46
  scope ||= Devise::Mapping.find_scope!(resource_or_scope)
47
47
  resource ||= resource_or_scope
48
+ warden.instance_variable_get(:@users).delete(scope)
48
49
  warden.session_serializer.store(resource, scope)
49
50
  end
50
51
 
@@ -106,8 +107,8 @@ module Devise
106
107
  env["warden.options"] = options
107
108
  Warden::Manager._run_callbacks(:before_failure, env, options)
108
109
 
109
- status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
110
- @controller.send :render, :status => status, :text => body,
110
+ status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
111
+ @controller.send :render, :status => status, :text => response.body,
111
112
  :content_type => headers["Content-Type"], :location => headers["Location"]
112
113
  nil # causes process return @response
113
114
  end
@@ -0,0 +1,14 @@
1
+ require "active_support/core_ext/module/delegation"
2
+
3
+ module Devise
4
+ class TimeInflector
5
+ include ActionView::Helpers::DateHelper
6
+
7
+ class << self
8
+ attr_reader :instance
9
+ delegate :time_ago_in_words, :to => :instance
10
+ end
11
+
12
+ @instance = new
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "2.1.4".freeze
2
+ VERSION = "2.2.0.rc".freeze
3
3
  end
@@ -27,7 +27,11 @@ module ActiveRecord
27
27
  attr_accessible :email, :password, :password_confirmation, :remember_me
28
28
  CONTENT
29
29
 
30
- class_path = class_name.to_s.split("::")
30
+ class_path = if namespaced?
31
+ class_name.to_s.split("::")
32
+ else
33
+ [class_name]
34
+ end
31
35
 
32
36
  indent_depth = class_path.size - 1
33
37
  content = content.split("\n").map { |line| " " * indent_depth + line } .join("\n") << "\n"
@@ -22,9 +22,6 @@ module Mongoid
22
22
  ## Database authenticatable
23
23
  field :email, :type => String, :default => ""
24
24
  field :encrypted_password, :type => String, :default => ""
25
-
26
- validates_presence_of :email
27
- validates_presence_of :encrypted_password
28
25
 
29
26
  ## Recoverable
30
27
  field :reset_password_token, :type => String
@@ -21,11 +21,15 @@ Some setup you must do manually if you haven't yet:
21
21
  <p class="notice"><%= notice %></p>
22
22
  <p class="alert"><%= alert %></p>
23
23
 
24
- 4. If you are deploying Rails 3.1 on Heroku, you may want to set:
24
+ 4. If you are deploying Rails 3.1+ on Heroku, you may want to set:
25
25
 
26
26
  config.assets.initialize_on_precompile = false
27
27
 
28
28
  On config/application.rb forcing your application to not access the DB
29
29
  or load models when precompiling your assets.
30
30
 
31
+ 5. You can copy Devise views (for customization) to your app by running:
32
+
33
+ rails g devise:views
34
+
31
35
  ===============================================================================
@@ -92,6 +92,14 @@ Devise.setup do |config|
92
92
  # the user cannot access the website without confirming his account.
93
93
  # config.allow_unconfirmed_access_for = 2.days
94
94
 
95
+ # A period that the user is allowed to confirm their account before their
96
+ # token becomes invalid. For example, if set to 3.days, the user can confirm
97
+ # their account within 3 days after the mail was sent, but on the fourth day
98
+ # their account can't be confirmed with the token any more.
99
+ # Default is nil, meaning there is no restriction on how long a user can take
100
+ # before confirming their account.
101
+ # config.confirm_within = 3.days
102
+
95
103
  # If true, requires any email changes to be confirmed (exactly the same way as
96
104
  # initial account confirmation) to be applied. Requires additional unconfirmed_email
97
105
  # db field (see migrations). Until confirmed new email is stored in
@@ -113,8 +121,8 @@ Devise.setup do |config|
113
121
  # config.rememberable_options = {}
114
122
 
115
123
  # ==> Configuration for :validatable
116
- # Range for password length. Default is 6..128.
117
- # config.password_length = 6..128
124
+ # Range for password length. Default is 8..128.
125
+ config.password_length = 8..128
118
126
 
119
127
  # Email regex used to validate email formats. It simply asserts that
120
128
  # an one (and only one) @ exists in the given string. This is mainly
@@ -125,7 +133,7 @@ Devise.setup do |config|
125
133
  # The time you want to timeout the user session without activity. After this
126
134
  # time the user will be asked for credentials again. Default is 30 minutes.
127
135
  # config.timeout_in = 30.minutes
128
-
136
+
129
137
  # If true, expires auth token on session timeout.
130
138
  # config.expire_auth_token_on_timeout = false
131
139
 
@@ -229,4 +237,4 @@ Devise.setup do |config|
229
237
  # When using omniauth, Devise cannot automatically set Omniauth path,
230
238
  # so you need to do it manually. For the users scope, it would be:
231
239
  # config.omniauth_path_prefix = "/my_engine/users/auth"
232
- end
240
+ end
@@ -1,4 +1,4 @@
1
- Welcome <%= @resource.email %>!
1
+ Welcome <%= @email %>!
2
2
 
3
3
  You can confirm your account through the link below:
4
4
 
@@ -1,6 +1,6 @@
1
1
  Hello <%= @resource.email %>!
2
2
 
3
- Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
3
+ Your account has been locked due to an excessive number of unsuccessful sign in attempts.
4
4
 
5
5
  Click the link below to unlock your account:
6
6
 
@@ -2,9 +2,10 @@
2
2
 
3
3
  <%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
4
4
  <%= f.error_notification %>
5
+ <%= f.full_error :confirmation_token %>
5
6
 
6
7
  <div class="form-inputs">
7
- <%= f.input :email, :required => true %>
8
+ <%= f.input :email, :required => true, :autofocus => true %>
8
9
  </div>
9
10
 
10
11
  <div class="form-actions">
@@ -7,7 +7,7 @@
7
7
  <%= f.full_error :reset_password_token %>
8
8
 
9
9
  <div class="form-inputs">
10
- <%= f.input :password, :label => "New password", :required => true %>
10
+ <%= f.input :password, :label => "New password", :required => true, :autofocus => true %>
11
11
  <%= f.input :password_confirmation, :label => "Confirm your new password", :required => true %>
12
12
  </div>
13
13
 
@@ -4,7 +4,7 @@
4
4
  <%= f.error_notification %>
5
5
 
6
6
  <div class="form-inputs">
7
- <%= f.input :email, :required => true %>
7
+ <%= f.input :email, :required => true, :autofocus => true %>
8
8
  </div>
9
9
 
10
10
  <div class="form-actions">
@@ -5,6 +5,11 @@
5
5
 
6
6
  <div class="form-inputs">
7
7
  <%= f.input :email, :required => true, :autofocus => true %>
8
+
9
+ <% if resource.class.reconfirmable && resource.unconfirmed_email.present? %>
10
+ <p>Currently waiting confirmation for: <%= resource.unconfirmed_email %></p>
11
+ <% end %>
12
+
8
13
  <%= f.input :password, :autocomplete => "off", :hint => "leave it blank if you don't want to change it", :required => false %>
9
14
  <%= f.input :password_confirmation, :required => false %>
10
15
  <%= f.input :current_password, :hint => "we need your current password to confirm your changes", :required => true %>
@@ -2,9 +2,10 @@
2
2
 
3
3
  <%= simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
4
4
  <%= f.error_notification %>
5
+ <%= f.full_error :unlock_token %>
5
6
 
6
7
  <div class="form-inputs">
7
- <%= f.input :email, :required => true %>
8
+ <%= f.input :email, :required => true, :autofocus => true %>
8
9
  </div>
9
10
 
10
11
  <div class="form-actions">
@@ -95,6 +95,12 @@ class HelpersTest < ActionController::TestCase
95
95
  assert_equal 'devise custom options', flash[:notice]
96
96
  end
97
97
 
98
+ test 'allows custom i18n options to override resource_name' do
99
+ I18n.expects(:t).with("custom_resource_name.confirmed", anything)
100
+ @controller.stubs(:devise_i18n_options).returns(:resource_name => "custom_resource_name")
101
+ @controller.send :set_flash_message, :notice, :confirmed
102
+ end
103
+
98
104
  test 'navigational_formats not returning a wild card' do
99
105
  MyController.send(:public, :navigational_formats)
100
106
  Devise.navigational_formats = [:"*/*", :html]
@@ -13,6 +13,34 @@ class SessionsControllerTest < ActionController::TestCase
13
13
  end
14
14
  end
15
15
 
16
+ test "#create delete the url stored in the session if the requested format is navigational" do
17
+ request.env["devise.mapping"] = Devise.mappings[:user]
18
+ request.session["user_return_to"] = 'foo.bar'
19
+
20
+ user = create_user
21
+ user.confirm!
22
+ post :create, :user => {
23
+ :email => user.email,
24
+ :password => user.password
25
+ }
26
+
27
+ assert_nil request.session["user_return_to"]
28
+ end
29
+
30
+ test "#create doesn't delete the url stored in the session if the requested format is not navigational" do
31
+ request.env["devise.mapping"] = Devise.mappings[:user]
32
+ request.session["user_return_to"] = 'foo.bar'
33
+
34
+ user = create_user
35
+ user.confirm!
36
+ post :create, :format => 'json', :user => {
37
+ :email => user.email,
38
+ :password => user.password
39
+ }
40
+
41
+ assert_equal 'foo.bar', request.session["user_return_to"]
42
+ end
43
+
16
44
  test "#create doesn't raise exception after Warden authentication fails when TestHelpers included" do
17
45
  request.env["devise.mapping"] = Devise.mappings[:user]
18
46
  post :create, :user => {
@@ -23,6 +51,20 @@ class SessionsControllerTest < ActionController::TestCase
23
51
  assert_template "devise/sessions/new"
24
52
  end
25
53
 
54
+ test "#destroy doesn't set the flash if the requested format is not navigational" do
55
+ request.env["devise.mapping"] = Devise.mappings[:user]
56
+ user = create_user
57
+ user.confirm!
58
+ post :create, :format => 'json', :user => {
59
+ :email => user.email,
60
+ :password => user.password
61
+ }
62
+
63
+ delete :destroy, :format => 'json'
64
+ assert flash[:notice].blank?, "flash[:notice] should be blank, not #{flash[:notice].inspect}"
65
+ assert_equal 204, @response.status
66
+ end
67
+
26
68
  if defined?(ActiveRecord) && ActiveRecord::Base.respond_to?(:mass_assignment_sanitizer)
27
69
  test "#new doesn't raise mass-assignment exception even if sign-in key is attr_protected" do
28
70
  request.env["devise.mapping"] = Devise.mappings[:user]
@@ -40,4 +82,4 @@ class SessionsControllerTest < ActionController::TestCase
40
82
  end
41
83
  end
42
84
  end
43
- end
85
+ end
@@ -68,5 +68,16 @@ class DeviseTest < ActiveSupport::TestCase
68
68
  end
69
69
  assert_not Devise.secure_compare("size_1", "size_four")
70
70
  end
71
-
71
+
72
+ test 'Devise.email_regexp should match valid email addresses' do
73
+ valid_emails = ["test@example.com", "jo@jo.co", "f4$_m@you.com", "testing.example@example.com.ua"]
74
+ non_valid_emails = ["rex", "test@go,com", "test user@example.com", "test_user@example server.com"]
75
+
76
+ valid_emails.each do |email|
77
+ assert_match Devise.email_regexp, email
78
+ end
79
+ non_valid_emails.each do |email|
80
+ assert_no_match Devise.email_regexp, email
81
+ end
82
+ end
72
83
  end
@@ -14,6 +14,12 @@ if DEVISE_ORM == :active_record
14
14
  assert_migration "db/migrate/devise_create_monsters.rb", /def change/
15
15
  end
16
16
 
17
+ test "all files for namespaced model are properly created" do
18
+ run_generator %w(admin/monster)
19
+ assert_file "app/models/admin/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
20
+ assert_migration "db/migrate/devise_create_admin_monsters.rb", /def change/
21
+ end
22
+
17
23
  test "update model migration when model exists" do
18
24
  run_generator %w(monster)
19
25
  assert_file "app/models/monster.rb"
@@ -66,4 +72,4 @@ if DEVISE_ORM == :active_record
66
72
  end
67
73
  end
68
74
  end
69
- end
75
+ end