devise_token_auth undefined method 'create_token' issue - ruby-on-rails-5

In my rails 5 application I have used "devise_token_auth" gem for developing token based API's for authentication purpose. Till date everything was working good, but suddenly I am getting below error,
NoMethodError (undefined method `create_token' for #<User:0x00000002268570>
Could not find any solution on google. Below is the full error,
Started POST "/api/v1/auth/sign_in" for ::1 at 2018-06-05 16:32:34 +0530
(28.8ms) SET NAMES utf8, ##SESSION.sql_mode = CONCAT(CONCAT(##sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), ##SESSION.sql_auto_is_null = 0, ##SESSION.wait_timeout = 2147483
(11.0ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
Processing by DeviseTokenAuth::SessionsController#create as */*
Parameters: {"email"=>"admin#example.com", "password"=>"[FILTERED]", "session"=>{"email"=>"admin#example.com", "password"=>"[FILTERED]"}}
Unpermitted parameter: :session
Unpermitted parameter: :session
User Load (12.3ms) SELECT `users`.* FROM `users` WHERE (BINARY email = 'admin#example.com' AND provider='email') ORDER BY `users`.`id` ASC LIMIT 1
Unpermitted parameter: :session
Unpermitted parameter: :session
Completed 500 Internal Server Error in 395ms (ActiveRecord: 92.9ms)
NoMethodError (undefined method `create_token' for #<User:0x00000002268570>
Did you mean? created_at):

I solved this error by using the Excluding Modules section of the docs.
# app/models/user.rb
class User < ActiveRecord::Base
# notice this comes BEFORE the include statement below
# also notice that :confirmable is not included in this block
devise :database_authenticatable, :recoverable,
:trackable, :validatable, :registerable,
:omniauthable
# note that this include statement comes AFTER the devise block above
include DeviseTokenAuth::Concerns::User
end
Including the DeviseTokenAuth::Concerns::User was what solved the undefined method problem, but I needed this section because it required confirmation (I put the include before the devise block)

Related

Devise - forgot password - no route matches [GET] "/users/password"

I just implemented the password reset function via devise but after following the link I receive per email and resetting my password I get the following error:
No route matches [GET] "/users/password" (Routing Error)
I would assume the routing works through devise?
My code in routes.rb looks like this:
devise_for :users, controllers: {
sessions: 'users/sessions',
passwords: 'users/passwords',
registrations: 'users/registrations'
}
I didn't change anything under controllers > users > passwords_controller.rb but in case it's helpful to see it, it looks like this:
class Users::PasswordsController < Devise::PasswordsController
# GET /resource/password/new
# def new
# super
# end
# POST /resource/password
# def create
# super
# end
# GET /resource/password/edit?reset_password_token=abcdef
# def edit
# super
# end
# PUT /resource/password
# def update
# super
# end
# protected
# def after_resetting_password_path_for(resource)
# super(resource)
# end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)
# super(resource_name)
# end
end
Am I missing anything or did I do something wrong?
When I add "get 'users/password'" to routes.rb, I get the error:
The action 'password' could not be found for UsersController (Unknown action)
Any help would be highly appreciated!
I had same issue and couldn't find any solution.
There can be two reasons for this error
there is no rails-ujs (or jquer-ujs) javascript file working on this page
no recoverable in User model
But in my case, there was no problem with these two, and password was changed after error page so I fixed this error by adding line in routes.rb as follows:
Rails.application.routes.draw do
get 'users/password', to: redirect("/")
end
Make sure that you have recoverable in User model:
class User
devise :database_authenticatable,
:registerable,
:validatable,
:recoverable
end
Please let me know if it does not help you.

Ruby validates_uniqueness_of email leading to wrong SQL uniqueness check

I am seeing the following SQL being used to check that an email address (e.g. joebloggs#joebloggs.com) is unique when a user signs up on my Ruby website:
SELECT `users`.id FROM `users` WHERE (`users`.`email` = BINARY '--- !ruby/object:Mail::Multibyte::Chars \nwrapped_string: joebloggs#joebloggs.com\n') LIMIT 1
This is always resulting in zero rows being returned, so Ruby attempts to create the user in the database. On the attempted record creation in MySQL, it fails because users.email has a unique index on it.
Can anyone tell me why Ruby is generating the SQL statement above? It does this on my live site running in production or development mode. On my development site (running in production or development mode), the following (correct) SQL is generated:
SELECT `users`.id FROM `users` WHERE (`users`.`email` = BINARY 'joebloggs#joebloggs.com') LIMIT 1
For user management, I am using devise with the following setting:
validates_uniqueness_of :email
Thanks in advance for your help.
In your user model you can add email validation to uniqueness as false.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,:registerable,
:recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:email]
validate :email, presence: true, uniqueness: false
end

devise reconfirmable

I would like to use the devise option :reconfirmable in my user model, so whenever a user changes his email, he needs to confirm it with a link sent by email.
The big problem is, that the email gets never sent ...
My setup is with devise 2.1.2 is:
user model:
attr_accessible: unconfirmed_email, ...
devise :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable
in the initilizer devise.rb:
config.reconfirmable = true
in the routes:
devise_for :users
in the form the model field unconfirmed_email gets set properly. I checked this through the console.
The first confirmation email, when a user registers on the page gets send out without problem.
I tried debugging the problem with adding this code to the initializers directory to overwrite the devise methode that gets triggered as a after_update hook:
module Devise::Models::Confirmable
def send_confirmation_instructions
debugger
end
end
it seems like send_confirmation_instructions is never called, since I never get to the debugger.
Do I somehow need to call reconfirmable, or does it gets triggered automatically when setting the model attribute "unconfirmed_email" to a new email address?
Thankfull for any help,
j.
OK, this is embarrassing..
After diving into the Devise code, I figured out that you don't need to set the unconfirmed_email attribute of your user model, but just change the existing email attribute. The attribute unconfirmed_email is just used internally for Devise to store the email address until it's confirmed.
Later version of devise gem explains this in initial migration. Here is "Confirmable" section (note the comment on the last line) from XXX_devise_create_users.rb migration:
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
Sorry for bothering, but hopefully this can help somebody having the same problem...

I need to authenticate a user directly in the console under Devise. How can I do it?

I need to do something like this from Rails console to do some testing and experiments:
User.authenticate(username, password)
I'm using Devise, but I have no idea how to do this.
I saw this other answer here
How to sign in a user using Devise from a Rails console?
But I need something cleaner and more direct. If necessary, I just need the algorithm to hash an attempted password with the salt and compare it to the encryped_password.
Is it this?
User.find(1).valid_password?('password123')
General info:
Check out the Devise README found here.
As an example, here is a helper method that you can use to do this test:
class User
def self.authenticate(username, password)
user = User.find_for_authentication(:username => username)
user.valid_password?(password) ? user : nil
end
end
Testing it, I get:
1.9.3p194 :001 > user = User.find(1)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User id: 1, {...USER DETAILS SHOWN HERE...}
1.9.3p194 :002 > user.valid_password?('is this it?')=> false
Also working: User.find(1).valid_password?('1') in Rails console:
1.9.3p194 :011 > User.find(1).valid_password?('1')
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> false
For reference, here's my Devise setup for the User model:
class User < ActiveRecord::Base`
devise :database_authenticatable, :registerable, :timeoutable, :recoverable, :rememberable, :trackable, :validatable
{...}
end
Like you said in the comments, there is no sessions_controller since Devise. Look into the Devise config file in /config/initializers/devise.rb. Depending on your application configuration, you may also want to look at the token.rb and session_store.rb initializer configs.
EDIT: Can you check your user model to see if devise is properly configured for it? Compare it against my devise line. The :validatable property could be missing.
EDIT 2: Added the helper method to do this test if you want to do it outside of the console. Check up top.
Side-note: The rails_admin gem is pretty useful and may be worth checking out!
Hope that helps.
I think implement can be much simpler without using any kind of gem.
At least we know the email id.
email : 'currentuser#email.com'
Current password: 'rubyuser'
user = User.find_by_email('currentuser#email.com')
user.valid_password?('wrong_password') #returns false
user.valid_password?('rubyuser') #returns true

Ruby on Rails Tutorial, Chapter 11, Exercise 7 - Breaks my rspec tests

I'm working through Michael Hartl's excellent tutorial on Rails, but I am having trouble with exercise 7 in Chapter 11.
This exercise is:
Add a nested route so that
/users/1/microposts shows all the
microposts for user 1. (You will also
have to add a Microposts controller
index action and corresponding view.)
I've done this successfully by changing my routes.rb file to read:
resources :users do
resources :microposts, :only => [:create, :destroy]
end
I am able to successfully call /users/1/microposts from a browser. However, most of the tests in microposts_controller_spec.rb are now broken. I receive the "no route matches" error when running autotest. For instance, the first test, which simply reads:
it "should deny access to 'create'" do
post :create
response.should redirect_to(signin_path)
end
now produces the following error:
1) MicropostsController access
control should deny access to 'create'
Failure/Error: post :create
No route matches {:controller=>"microposts",
:action=>"create"}
When I check rake routes
, I find this entry:
user_microposts POST /users/:user_id/microposts(.:format) {:action=>"create", :controller=>"microposts"}
which suggests the route does exist.
Has anyone else run into this issue while completing the tutorial? Is there a change I need to make in the spec file once I introduce nested routes? Does Rspec work with nested routes?
thanks
Because this is a nested route you will need to pass the user_id through:
some_user = way_of_creating_a_user_goes_here
post :create, :user_id => some_user.id
RSpec will attempt to go to the /microposts route without this parameter.