devise 0.2.2 → 0.2.3

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,13 @@
1
+ == 0.2.3
2
+
3
+ * enhancements
4
+ * Ensure fail! works inside strategies
5
+ * [#12] Make unauthenticated message (when you haven't signed in) different from invalid message
6
+
7
+ * bug fix
8
+ * Do not redirect on invalid authenticate
9
+ * Allow model configuration to be set to nil
10
+
1
11
  == 0.2.2
2
12
 
3
13
  * bug fix
@@ -70,7 +70,7 @@ Now let's setup a User model adding the devise line to have your authentication
70
70
  devise
71
71
  end
72
72
 
73
- This line adds devise authenticable automatically for you inside your User class. Devise don't rely on _attr_accessible_ or _attr_protected_ inside it's modules, so be sure to setup what attributes are accessible or protected in your model.
73
+ This line adds devise authenticable automatically for you inside your User class. Devise don't rely on _attr_accessible_ or _attr_protected_ inside its modules, so be sure to setup what attributes are accessible or protected in your model.
74
74
 
75
75
  You could also include the other devise modules as below:
76
76
 
@@ -107,6 +107,14 @@ In addition to :except, you can provide some options to devise call:
107
107
 
108
108
  devise :all, :stretches => 20
109
109
 
110
+ * confirm_in: the time the user can access the site before being blocked because his account was not confirmed
111
+
112
+ devise :all, :confirm_in => 1.week
113
+
114
+ * remember_for: the time to store the remember me cookie in the user
115
+
116
+ devise :all, :remember_for => 2.weeks
117
+
110
118
  The next step after setting up your model is to configure your routes for devise. You do this by opening up your config/routes.rb and adding:
111
119
 
112
120
  map.devise_for :users
@@ -168,9 +176,10 @@ After signing in a user, confirming it's account or updating it's password, devi
168
176
 
169
177
  map.root :controller => 'home'
170
178
 
171
- You also need to setup default url options for the mailer, if you are using confirmable or recoverable. It's a Rails required configuration, and you can do this inside your specific environments. Here is an example of development environment:
179
+ You also need to setup default url options for the mailer, if you are using confirmable or recoverable. Here's is the configuration for development:
172
180
 
173
- config.action_mailer.default_url_options = { :host => 'localhost:3000' }
181
+ Notifier.sender = "no-reply@yourapp.com"
182
+ ActionMailer::Base.default_url_options = { :host => 'localhost:3000' }
174
183
 
175
184
  Devise let's you setup as many roles as you want, so let's say you already have this User model and also want an Admin model with the same authentication stuff, but not confirmation or password recovery. Just follow the same steps:
176
185
 
@@ -209,14 +218,14 @@ This is gonna copy all session, password, confirmation and notifier views to you
209
218
 
210
219
  == I18n
211
220
 
212
- Devise check for flash messages using i18n, so you're able to customize them easily. For example, to change the sign in message you should setup your locale file this way:
221
+ Devise uses flash messages with I18n with the flash keys :success and :failure. To customize your app, you can setup your locale file this way:
213
222
 
214
223
  en:
215
224
  devise:
216
225
  sessions:
217
226
  signed_in: 'Signed in successfully.'
218
227
 
219
- You can also create distinct messages based on the resource you've configured:
228
+ You can also create distinct messages based on the resource you've configured using the singular name given in routes:
220
229
 
221
230
  en:
222
231
  devise:
@@ -226,7 +235,7 @@ You can also create distinct messages based on the resource you've configured:
226
235
  admin:
227
236
  signed_in: 'Hello admin!'
228
237
 
229
- Devise notifier uses the same pattern to create subject messages, but it is not able to know what scope you are, he just know the record (ie user instance) that was sent to it. So you need to customize messages based on the model class name (usually the same as the resource name, if you follow basic conventions):
238
+ Devise notifier uses the same pattern to create subject messages:
230
239
 
231
240
  en:
232
241
  devise:
@@ -1,12 +1,19 @@
1
1
  class SessionsController < ApplicationController
2
2
  include Devise::Controllers::Helpers
3
3
 
4
+ # Maps the messages types that comes from warden to a flash type.
5
+ WARDEN_MESSAGES = {
6
+ :unauthenticated => :success,
7
+ :unconfirmed => :failure
8
+ }
9
+
4
10
  before_filter :require_no_authentication, :only => [ :new, :create ]
5
11
 
6
12
  # GET /resource/sign_in
7
13
  def new
8
- unauthenticated! if params[:unauthenticated]
9
- unconfirmed! if params[:unconfirmed]
14
+ WARDEN_MESSAGES.each do |message, type|
15
+ set_now_flash_message type, message if params.key?(message)
16
+ end
10
17
  build_resource
11
18
  end
12
19
 
@@ -16,7 +23,7 @@ class SessionsController < ApplicationController
16
23
  set_flash_message :success, :signed_in
17
24
  redirect_back_or_to home_or_root_path
18
25
  else
19
- unauthenticated!
26
+ set_now_flash_message :failure, :invalid
20
27
  build_resource
21
28
  render :new
22
29
  end
@@ -29,14 +36,4 @@ class SessionsController < ApplicationController
29
36
  redirect_to root_path
30
37
  end
31
38
 
32
- protected
33
-
34
- def unauthenticated!
35
- set_now_flash_message :failure, :unauthenticated
36
- end
37
-
38
- def unconfirmed!
39
- set_now_flash_message :failure, :unconfirmed
40
- end
41
-
42
39
  end
@@ -16,12 +16,15 @@ class Notifier < ::ActionMailer::Base
16
16
 
17
17
  # Configure default email options
18
18
  def setup_mail(record, key)
19
- subject translate(record, key)
19
+ mapping = Devise.mappings.values.find { |m| m.to == record.class }
20
+ raise "Invalid devise resource #{record}" unless mapping
21
+
22
+ subject translate(mapping, key)
20
23
  from self.class.sender
21
24
  recipients record.email
22
25
  sent_on Time.now
23
26
  content_type 'text/html'
24
- body underscore_name(record) => record, :resource => record
27
+ body mapping.name => record, :resource => record
25
28
  end
26
29
 
27
30
  # Setup subject namespaced by model. It means you're able to setup your
@@ -35,13 +38,7 @@ class Notifier < ::ActionMailer::Base
35
38
  # user:
36
39
  # notifier:
37
40
  # confirmation_instructions: '...'
38
- def translate(record, key)
39
- I18n.t(:"#{underscore_name(record)}.#{key}",
40
- :scope => [:devise, :notifier],
41
- :default => key)
42
- end
43
-
44
- def underscore_name(record)
45
- @underscore_name ||= record.class.name.underscore.to_sym
41
+ def translate(mapping, key)
42
+ I18n.t(:"#{mapping.name}.#{key}", :scope => [:devise, :notifier], :default => key)
46
43
  end
47
44
  end
@@ -3,8 +3,9 @@ en:
3
3
  sessions:
4
4
  signed_in: 'Signed in successfully.'
5
5
  signed_out: 'Signed out successfully.'
6
- unauthenticated: 'Invalid email or password.'
6
+ unauthenticated: 'You need to sign in or sign up before continuing.'
7
7
  unconfirmed: 'Your account was not confirmed and your confirmation period has expired.'
8
+ invalid: 'Invalid email or password.'
8
9
  passwords:
9
10
  send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
10
11
  updated: 'Your password was changed successfully. You are now signed in.'
@@ -38,7 +38,9 @@ module Devise
38
38
 
39
39
  mod.const_get(:ClassMethods).class_eval <<-METHOD, __FILE__, __LINE__
40
40
  def #{accessor}
41
- @#{accessor} || if superclass.respond_to?(:#{accessor})
41
+ if defined?(@#{accessor})
42
+ @#{accessor}
43
+ elsif superclass.respond_to?(:#{accessor})
42
44
  superclass.#{accessor}
43
45
  else
44
46
  Devise.#{accessor}
@@ -78,9 +78,12 @@ module Devise
78
78
  instance_variable_set(:"@#{resource_name}", new_resource)
79
79
  end
80
80
 
81
- # Build a devise resource
81
+ # Build a devise resource without setting password and password confirmation fields.
82
82
  def build_resource
83
- self.resource = resource_class.new(params[resource_name])
83
+ self.resource ||= begin
84
+ attributes = params[resource_name].try(:except, :password, :password_confirmation)
85
+ resource_class.new(attributes)
86
+ end
84
87
  end
85
88
 
86
89
  # Helper for use in before_filters where no authentication is required.
@@ -8,8 +8,12 @@ module Devise
8
8
  # to the default_url.
9
9
  def self.call(env)
10
10
  options = env['warden.options']
11
- params = options[:params] || {}
12
11
  scope = options[:scope]
12
+ params = if env['warden'].try(:message)
13
+ { env['warden'].message => true }
14
+ else
15
+ options[:params]
16
+ end
13
17
 
14
18
  redirect_path = if mapping = Devise.mappings[scope]
15
19
  "/#{mapping.as}/#{mapping.path_names[:sign_in]}"
@@ -19,7 +23,7 @@ module Devise
19
23
 
20
24
  headers = {}
21
25
  headers["Location"] = redirect_path
22
- headers["Location"] << "?" << Rack::Utils.build_query(params) unless params.empty?
26
+ headers["Location"] << "?" << Rack::Utils.build_query(params) if params
23
27
  headers["Content-Type"] = 'text/plain'
24
28
 
25
29
  message = options[:message] || "You are being redirected to #{redirect_path}"
@@ -7,12 +7,16 @@ module Devise
7
7
  # Authenticate a user based on email and password params, returning to warden
8
8
  # success and the authenticated user if everything is okay. Otherwise redirect
9
9
  # to sign in page.
10
+ #
11
+ # Please notice the semantic difference between calling fail! and throw :warden.
12
+ # The first does not perform any action when calling authenticate, just
13
+ # when authenticate! is invoked. The second always perform the action.
10
14
  def authenticate!
11
15
  if valid_attributes? && resource = mapping.to.authenticate(attributes)
12
16
  success!(resource)
13
17
  else
14
18
  store_location
15
- throw :warden, :scope => scope, :params => { :unauthenticated => true }
19
+ fail!(:unauthenticated)
16
20
  end
17
21
  end
18
22
 
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "0.2.2".freeze
2
+ VERSION = "0.2.3".freeze
3
3
  end
@@ -81,8 +81,6 @@ class AuthenticationTest < ActionController::IntegrationTest
81
81
  fill_in 'email', :with => 'wrongemail@test.com'
82
82
  end
83
83
 
84
- assert_redirected_to new_admin_session_path(:unauthenticated => true)
85
- follow_redirect!
86
84
  assert_contain 'Invalid email or password'
87
85
  assert_not warden.authenticated?(:admin)
88
86
  end
@@ -92,8 +90,6 @@ class AuthenticationTest < ActionController::IntegrationTest
92
90
  fill_in 'password', :with => 'abcdef'
93
91
  end
94
92
 
95
- assert_redirected_to new_admin_session_path(:unauthenticated => true)
96
- follow_redirect!
97
93
  assert_contain 'Invalid email or password'
98
94
  assert_not warden.authenticated?(:admin)
99
95
  end
@@ -101,13 +97,12 @@ class AuthenticationTest < ActionController::IntegrationTest
101
97
  test 'error message is configurable by resource name' do
102
98
  begin
103
99
  I18n.backend.store_translations(:en, :devise => { :sessions =>
104
- { :admin => { :unauthenticated => "Invalid credentials" } } })
100
+ { :admin => { :invalid => "Invalid credentials" } } })
105
101
 
106
102
  sign_in_as_admin do
107
103
  fill_in 'password', :with => 'abcdef'
108
104
  end
109
105
 
110
- follow_redirect!
111
106
  assert_contain 'Invalid credentials'
112
107
  ensure
113
108
  I18n.reload!
@@ -145,14 +140,14 @@ class AuthenticationTest < ActionController::IntegrationTest
145
140
  assert_not_contain 'Signed out successfully'
146
141
  end
147
142
 
148
- test 'redirect from warden shows error message' do
143
+ test 'redirect from warden shows sign in or sign up message' do
149
144
  get admins_path
150
145
 
151
146
  warden_path = new_admin_session_path(:unauthenticated => true)
152
147
  assert_redirected_to warden_path
153
148
 
154
149
  get warden_path
155
- assert_contain 'Invalid email or password.'
150
+ assert_contain 'You need to sign in or sign up before continuing.'
156
151
  end
157
152
 
158
153
  test 'render 404 on roles without permission' do
@@ -13,6 +13,7 @@ ActionMailer::Base.default_url_options[:host] = 'test.com'
13
13
  ActiveRecord::Migration.verbose = false
14
14
  ActiveRecord::Base.logger = Logger.new(nil)
15
15
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
16
+
16
17
  ActiveRecord::Schema.define(:version => 1) do
17
18
  [:users, :admins].each do |table|
18
19
  create_table table do |t|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Jos\xC3\xA9 Valim"
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-10-28 00:00:00 -02:00
13
+ date: 2009-10-29 00:00:00 -02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency