Rails 4 Beta Compatibility #2172

Closed
wants to merge 15 commits into from
@idl3

Using the current guidelines by Rails 4, I have modified devise to adhere to Strong Parameters when detected to be running on a Rails 4 App. It also removes attr_accessible generation.

Routes have been modified to have GET headers instead of Match.

@josevalim josevalim commented on an outdated diff Dec 10, 2012
@@ -162,6 +162,25 @@ current_member
member_session
```
+### Rails 4 Beta
+
+By default Devise will whitelist [:email, :password, :password_confirmation, :password_current] on install. However in Rails 4.0, Strong Parameters requires any additional parameters to be explicitly permitted. As permission logic should be in the controller by nature, you would need to create a custom controller and define your permissions there.
+
+```ruby
+#config/routes.rb
+devise_for :users, :controllers => { :registrations => "custom_controller" }
+
+#apps/controllers/registrations_controller.rb
+class RegistrationsController < Devise::RegistrationsController
+ before_filter :permissions
+
+ def permissions
+ # Redefine the list of permissible parameters
+ devise_permitted [:name, :email, :password, :password_confirmation, :password_current]
@josevalim
Plataformatec member

:current_password

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@josevalim josevalim and 1 other commented on an outdated diff Dec 10, 2012
app/controllers/devise_controller.rb
@@ -96,17 +110,20 @@ def resource=(new_resource)
# Build a devise resource.
# Assignment bypasses attribute protection when :unsafe option is passed
def build_resource(hash = nil, options = {})
- hash ||= resource_params || {}
-
- if options[:unsafe]
- self.resource = resource_class.new.tap do |resource|
- hash.each do |key, value|
- setter = :"#{key}="
- resource.send(setter, value) if resource.respond_to?(setter)
+ if Devise::RAILS4
+ self.resource = resource_params ? resource_class.new(permitted_params) : resource_class.new
+ else
@josevalim
Plataformatec member

Why do we need this branch?

@idl3
idl3 added a note Dec 10, 2012

As in the purpose for the commits? Or why I created a rails4 branch?

If its the purpose of this push, I was getting StrongParameter errors and was unable to create/update registrations on a Rails 4 project as of now. If its why I created the branch, its purely for my local dev purposes, this was meant to go in master for compatibility with 4.0.0.beta

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@VadimPushtaev

As permission logic should be in the controller by nature, you would need to create a custom controller and define your permissions there.

Is it reasonable to make default Devise controller flexible enough for letting users change white-list without creating their own controllers, but just with providing some config options?

@idl3

You reckon it should be thrown into the devise initializer? If so it should also cater for multiple resources.

Like maybe a

config.params_whitelist = [
  :staff => [:email, :password, :password_confirmation, :current_password], 
  :client => [:username, :password, :password_confirmation, :current_password]
]
@VadimPushtaev

I suppose it's overkill, no need to make controller so flexible.

I suggest parameterizing only global whitelist which is used when devise_permitted is called without params. This way we let programmers use simple way for simple cases and complicate way for complicated cases.

Anyway, it's tricky decision, we should ask @josevalim how many flexibility Devise should have.

@lporras

I'm trying to use devise with rails 4.0.0.beta and when I run bundle install y get this:

Bundler could not find compatible versions for gem "railties":
 In Gemfile:
   devise (>= 0) ruby depends on
     railties (~> 3.1) ruby

   rails (>= 0) ruby depends on
     railties (4.0.0.beta)

also if I have gem 'devise' in my Gemfile then devise '1.5.0' is installed and it don't let me update it, with this version I get errors releated with strong_parameters

@idl3

Are you using this branch as your Gemfile source?
Make sure your Gemfile has a github source and branch as follows

gem 'devise', github: 'idl3/devise', branch: 'rails4'
@lporras

@idl3 Using that branch solved the installation problem but when I ran the user generator I got some errors

@idl3

Oh can you show me what the errors are?

@jlxw

I agree we should have a rails4 branch at least...

@idl3

Modified the code to now accept whitelists via devise.rb
Out of the box without configuration this branch will work on rails4

#config/initializers/devise.rb

# If you wish to add an extra permitted parameter you can add it to the array as follows
config.params_whitelist << :username

# If you wish further customize and redefine your permitted parameters you can do so via an assignment
# e.g. adding username to the list but removing email
config.params_whitelist = [:username, :password, :password_confirmation, :current_password] 
#note that current_password will need to be permitted for updating of resource

The option for custom controller based also works

devise_permitted [options]
@h3h h3h and 1 other commented on an outdated diff Feb 3, 2013
lib/devise.rb
@@ -31,6 +32,7 @@ module Strategies
# Constants which holds devise configuration for extensions. Those should
# not be modified by the "end user" (this is why they are constants).
+ RAILS4 = %r(4.0).match(Rails.version) ? true : false
@h3h
h3h added a note Feb 3, 2013

Guessing you probably want something closer to %r(^4\.)

>> ["3.4.0", "3.410", "4.0", "4.1"].map {|s| !!%r(4.0).match(s) }
=> [true, true, true, false]

>> ["3.4.0", "3.410", "4.0", "4.1"].map {|s| !!%r(^4\.).match(s) }
=> [false, false, true, true]
@idl3
idl3 added a note Feb 3, 2013

Yeah 👍 you wanna do a pull req?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@denispeplin

I'm tried to use devise gem from rails4 branch, but it seems incompatible with ActionController::Live. So I've got the error:

Started GET "/" for 127.0.0.1 at 2013-02-06 10:29:43 +0400
Processing by MessagesController#index as HTML
Completed 500 Internal Server Error in 35ms
Exiting
/var/lib/gems/1.9.1/gems/warden-1.2.1/lib/warden/proxy.rb:128:in `throw': uncaught throw :warden (ArgumentError)
        from /var/lib/gems/1.9.1/gems/warden-1.2.1/lib/warden/proxy.rb:128:in `authenticate!'
        from /home/den/.bundler/ruby/1.9.1/devise-a18024b7f3b9/lib/devise/controllers/helpers.rb:48:in `authenticate_user!'
        from /home/den/forks/rails/activesupport/lib/active_support/callbacks.rb:407:in `_run__3596402370548024027__process_action__callbacks'
        from /home/den/forks/rails/activesupport/lib/active_support/callbacks.rb:78:in `run_callbacks'
        from /home/den/forks/rails/actionpack/lib/abstract_controller/callbacks.rb:17:in `process_action'
        from /home/den/forks/rails/actionpack/lib/action_controller/metal/rescue.rb:29:in `process_action'
        from /home/den/forks/rails/actionpack/lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
        from /home/den/forks/rails/activesupport/lib/active_support/notifications.rb:158:in `block in instrument'
        from /home/den/forks/rails/activesupport/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
        from /home/den/forks/rails/activesupport/lib/active_support/notifications.rb:158:in `instrument'
        from /home/den/forks/rails/actionpack/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
        from /home/den/forks/rails/actionpack/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
        from /home/den/forks/rails/activerecord/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
        from /home/den/forks/rails/actionpack/lib/abstract_controller/base.rb:136:in `process'
        from /home/den/forks/rails/actionpack/lib/abstract_controller/rendering.rb:44:in `process'
        from /home/den/forks/rails/actionpack/lib/action_controller/metal/live.rb:118:in `block in process'

After disabling ActionController::Live module, application shows sign_in page as usual.

@jlxw

seems like there's an official rails4 branch now, is it ready to be used?

@denispeplin

As (temporary?) solution to described above problem with ActionController::Live I moved action, that requires this module, to separate controller. All that left is to figure out how to pass current_user via javascript to this action in secure way.

@carlosantoniodasilva

Hey folks, the rails4 branch is now green with current Rails master, using the protected_attributes gem. The next step is to provide integration with strong_parameters, but for now if any of you is using protected_attrs in a migrating app and can give it a try on that branch, that'd be awesome :).

@josevalim josevalim closed this Feb 25, 2013
@joallard

So, seeing this has closed, does it work with Strong Parameters now? /@josevalim

@rafaelfranca

Not yet.

@eljojo

Hi, I have an idea of how we can implement strong_parameters support.

registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  private
    def resource_params
      params[resource_name] = params[:registration] if params[:registration] and not params[resource_name]
      params.require(resource_name).permit(resource_name.to_s.classify.constantize.devise_resource_params)
    end
end

user.rb User model, for instance

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :token_authenticatable,
         :recoverable, :rememberable, :trackable, :validatable

  # attr_accessible is soooo last year

  def self.devise_resource_params
    [:first_name, :last_name, :email, :email_alias, :password, :password_confirmation, :current_password]
  end
end

what do you guys think about?

@nashby nashby referenced this pull request Mar 6, 2013
Closed

Rails 4.0 support? #2320

@pahnin

What is the best way to use this branch with rails4?
someone wrote above to use whitelist and someone wrote using protected_atrributes, etc.,

Is there any standard way which would be supported in the next release? So that I can use it now and my application would not break when there is an update to devise?

@joallard

@pahnin: well in principle, you have integration tests to tell you when something breaks after you (change/update) something

@pahnin

I've used "idl3/device rails4" there's a small problem. I had to add email to whitelist too, for the signup to work.

@idl3

Yeah you've got to add whatever attributes you would require to the whitelist. My example above was for an app that signed in with a username instead of an email :)

@dimension64

I'm not able to use Devise with Rails 4. I'm getting the following error.
/home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/application/routes_reloader.rb:10:in rescue in execute_if_updated': Rails::Application::RoutesReloader#execute_if_updated delegated to updater.execute_if_updated, but updater is nil: #<Rails::Application::RoutesReloader:0x93f10fc @paths=["/home/p4/rails_tut/real_app/config/routes.rb"], @route_sets=[#<ActionDispatch::Routing::RouteSet:0x978e368>]> (RuntimeError)
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/application/routes_reloader.rb:6:in
execute_if_updated'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/application/finisher.rb:69:in block in <module:Finisher>'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/initializable.rb:30:in
instance_exec'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/initializable.rb:30:in run'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/initializable.rb:55:in
block in run_initializers'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:150:in block in tsort_each'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:183:in
block (2 levels) in each_strongly_connected_component'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:219:in each_strongly_connected_component_from'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:182:in
block in each_strongly_connected_component'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:180:in each'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:180:in
each_strongly_connected_component'
from /home/p4/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb:148:in tsort_each'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/initializable.rb:54:in
run_initializers'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/application.rb:215:in initialize!'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/railtie/configurable.rb:30:in
method_missing'
from /home/p4/rails_tut/real_app/config/environment.rb:5:in <top (required)>'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in
require'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in block in require'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:213:in
load_dependency'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0/lib/active_support/dependencies.rb:228:in require'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/application.rb:189:in
require_environment!'
from /home/p4/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands.rb:45:in <top (required)>'
from bin/rails:4:in
require'
from bin/rails:4:in `

'

@grimmwerks

I just got the same error-- ah actually no; it was the install of the devise_security_extension I think...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment