I am using Devise in my Rails application. For some users I am getting this kind of error:
undefined method 'to' for nil:NilClass from this method
def http_auth_header?
Devise.mappings[scope].to.http_authenticatable && !request.xhr?
end
that is from Devise itself.
How can I resolve this?
I spent time to fix the same issue.
I did some custom stuff into the SessionController :
resource = warden.authenticate!(:scope => "user", :recall => "#{controller_path}#failure")
And in fact, scope MUST BE a symbol :
resource = warden.authenticate!(:scope => :user, :recall => "#{controller_path}#failure")
So I think you just provide a scope as a String instead of a symbol
Hope it helps ;)
Related
I have a controller create method like this.
def create
if user.save!
user.add_role = params[:user][:Role].parameterize('_').to_sym
if current_user.has_role?(:producer_or_beat_maker_or_composer)
#if(Student.find_by_email("#{current_user.email}")!= nil)
redirect_to(:controller => 'users',:action => new_registration_path(resource_name))
elsif current_user.role=="Producer"
redirect_to(:controller => 'users',:action => 'index')
end
end
end
when i click on user creation,i got an error like " undefined method `parameterize' for nil:NilClass". please help through this..
This one is quite simple params[:user][:Role] is nil. Perhaps you meant params[:user][:role].
It's possible to use form_authencity_token inside a controller in Rails.
def create
#user = self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
#csrfToken = form_authenticity_token
#user
end
My question is: is it possible to have form_authencity_value inside a spec? I'm testing a controller and a JSON response from SessionsController (Devise). And I have to update csrf-token constantly to don't get erros like: Can't verify CSRF token authenticity in my requests.
Please, I'm already sending to the server my csrf-token and it's working perfectly. My problem here is with RSpec, to test my RABL response after logging in (and logout - that is not a RABL view).
My test is something like this:
expected_response = {
'id' => #user.id,
'email' => #user.email,
'first_name' => #user.first_name,
'last_name' => #user.last_name,
'created_at' => #user.created_at,
'updated_at' => #user.updated_at,
'csrfToken' => # PROBLEM
}.to_json
expect(response.body).to eq(expected_response)
How can I have form_authencity_value inside my spec?
If you are able to assign it to #csrfToken, then what you need is:
{
# ...
#csrfToken' => assigns(:csrfToken)
}
The assigns method can dig up any controller instance variable you've set.
Another possibility is to stub out form_authenticity_token if you aren't assigning it to an instance variable.
expect(controller).to receive(:form_authenticity_token).and_return('a_known_value')
You can use expect or allow. Now you have a known value to compare against.
Devise throws:
"NoMethodError (undefined method `login' for #<ActionDispatch::Request:0x00000004e42d80>):
"
every time I try to log in.
In this application "login" field is used as authentication key:
/config/initializers/devise.rb:
config.authentication_keys = [ :login ]
In session_controller.rb I used before_filter:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:user) { |u| u.permit(:login, :password) }
end
And my routes.rb:
devise_for :users, :controllers => { :sessions => 'sessions', :registrations => 'registrations', :invitations => 'users/invitations'}
This problem appeared after upgrade from Rails 3 to Rails 4.
Can someone explain to me, what I'm doing wrong?
UPDATE
My bad. Found wrong parameter in devise initializer, set by my co-worker.
Anyway i have error message:
NameError (undefined local variable or method `invitation_token' for #<User:0x0000000286c750>):
app/controllers/sessions_controller.rb:6:in `create'
sessions#create:
def create
self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
render :json => { :user_id => resource.id }, :status => :created
end
UPDATE
Crap. My co-worker also changed database.yml to another DB. So this DB was not migrated to last state =. After rake db:migrate all works fine. Thanks to all.
The underlying issue here is generally that devise's invitable code is generated by an second step in your devise work flow, a generator that makes a second migration:
$ rails g devise_invitable:install
$ rails g devise_invitable User (where User is my Model)
$ rake db:migrate
What you need to check for is if both migrations are in sync (in my case I reran the user migration but NOT the invitable migration and thus my user table was incorrect).
According to this link, you should create a login virtual attribute in the User model.
#Virtual attribute for authenticating by either username or email
#This is in addition to a real persisted field like 'username'
attr_accessor :login
Also add login to attr_accessible for rails 3
attr_accessible :login
You may also need to overwrite Devise's find_for_database_authentication method in User model
(assuming it is activerecord)
# app/models/user.rb
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
You may need to modify config/initializers/devise.rb to have
config.reset_password_keys = [ :login ]
config.confirmation_keys = [ :login ]
I am using Clearance 1.1.0 gem with Ruby on Rails 4.0.1. I am trying to override the sessions controller to provide my own custom method. I have not been able to successfully get rails to use my controller.
/app/controllers/sessions_controller.rb
class SessionsController < Clearance::SessionsController
private
def flash_failure_after_create
flash.now[:notice] = translate(:bad_email_or_password,
:scope => [:clearance, :controllers, :sessions],
:default => t('flashes.failure_after_create', :new_password_path => new_password_path).html_safe)
end
end
I have tried a few different things inside my routes.rb file, and have been unsuccessful. I want to change the route sign_in.
get '/sign_in' => 'sessions#new', :as => 'sign_in'
Yields the following error.
You may have defined two routes with the same name using the :as
option, or you may be overriding a route already defined by a resource
with the same naming.
Any ideas? Thank you!
Edit: I made a mistake. I actually need sessions#create to use my controller. I'm trying to pass a different variable to the yaml file for the flash when the session login fails.
Edit 2: I the appropriate session#create line to to my routes. In my session controller, I copied and edited for testing the flash_failure_after_create method. It is not being called. So I then copy the create method over. Now, my create method is being called, but not my flash_failure_after_create method. To get it to be called, I had to have the create method copied from gem, and changed status.failure_message to directly call the flash_failure_after_create method. Is this some sort of bug with clearance?
routes.rb
post 'session' => 'sessions#create', :as => nil
sessions_controller.rb
class SessionsController < Clearance::SessionsController
def create
#user = authenticate(params)
sign_in(#user) do |status|
if status.success?
redirect_back_or url_after_create
else
#flash.now.notice = status.failure_message
flash.now.notice = flash_failure_after_create
render :template => 'sessions/new', :status => :unauthorized
end
end
end
private
def flash_failure_after_create
# Changed flash for easy testing
flash.now[:notice] = 'Ballz.'
#flash.now[:notice] = translate(:bad_email_or_password,
# :scope => [:clearance, :controllers, :sessions],
# :default => t('flashes.failure_after_create', :sign_up_path => sign_up_path).html_safe)
end
end
I believe this will work:
get '/sign_in' => 'sessions#new', :as => nil
Rails 4 no longer supports overriding route names, so don't name your override. The mapping is still the same so sign_in_path should still work.
I am getting the following error when I try to sign out of devise error:
No route matches [GET] "/d/users/sign_out"
My tag is correct, it is as follows:
<%= link_to "Sign Out", destroy_session_path, :method=>:delete %>
My route for devise is:
devise_for :users, :path_prefix=>"d", :controllers=>{:sessions=>"sessions"}
Other routes are:
resources :users#For CRUD defined after devise_for like in Devise Wiki
With a custom controller sessions for ajax login like on the Devise wiki page:
class SessionsController < Devise::SessionsController
def create
respond_to do |format|
format.html{ super }
format.json do
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
#resource = warden.authenticate!(:scope => resource_name, :recall => :failure)
return sign_in_and_redirect(resource_name, resource)
end
end
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true, :redirect => stored_location_for(scope) || after_sign_in_path_for(resource)}
end
def failure
return render:json => {:success => false, :errors => ["Login failed."]}
end
end
The devise initializer has:
config.sign_out_via = :delete
Any ideas on what could be causing the problem? I've searched Google and am still stumped.
Update:
Here is a screenshot of the rails routes file for the devise users. Sorry, it is small, but you can right-click then view it by itself for a larger screen.
Update #2:
The jquery_ujs file is included.
Update #3:
It appears in the console that delete is indeed being passed, but it is jumping from the sessions_controller to / then to d/users/sign_out...Not sure how to fix this.
Update #4:
When redirecting it goes first to d/users/sign_out as DELETE, as it should. It then redirects to root_url which then gives the error ERROR Errno::ECONNABORTED: An established connection was aborted by the software in your host machine. It then tries to redirect to d/users/sign_out as GET where it is failing.
This appears to be an issue between Devise and Ruby 1.9.2-p290. Updating to Ruby 1.9.3 and running bundle update to ensure the latest version of Devise was used; appears to work.
It sounds like you might have removed //= require jquery_ujs from your application.js file. I think that handles the link particulars to make a 'delete' request. Either way, as it is now, you're making a 'GET' which obviously won't hit your destroy_user_session method.
Change:
config.sign_out_via = :delete
to:
config.sign_out_via = :get
See this related:
No route matches "/users/sign_out" devise rails 3