devise forgot password setup - ruby-on-rails

I am really new to rails and have been trying to work on building an application. I recently have installed devise and omniauth for facebook with great success after some time. When I was reading into devise, I noticed that Devise has a "forgot password" module built into it.
I have scoured the internet and for the life of me haven't figured out how to set it up. Is there any guide?I have been working for hours, but I haven't really had any results. How do I set this up? I am using rails 4.0 and the newest version of devise.
Thanks,
Routes
Omrails::Application.routes.draw do
resources :boards
resources :pins
get 'about' => "pages#about"
root :to => 'pins#index'
resources :tests, :birthdays
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
end
Devise Migration:
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0, :null => false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
end
end
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:registerable,
:rememberable,
:trackable,
:recoverable,
:validatable,
:omniauthable,
:omniauth_providers => [:facebook]
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :birthday, :sex, :address, :mobile, :provider, :uid
has_many :pins, :dependent => :destroy
has_many :boards, :dependent => :destroy
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(name:auth.extra.raw_info.name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email,
password:Devise.friendly_token[0,20])
end
user
end
end

Devise consists of 10 modules and the one you're looking for is recoverable. In your devise model, you need to add :recoverable attribute for devise.

Related

Devise sign-up request method post using Postman

I created an only API rails project and added devise user model
now I am trying to sign-up using Postman but it does not save the new user on the
database
however, it does not return an error as well.
Postman post request and parameters passed
My app controller with the additional permitted attributes
`class ApplicationController < ActionController::API
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
attributes = :name, { roles: [] }
devise_parameter_sanitizer.permit(:sign_up, keys: attributes)
devise_parameter_sanitizer.permit(:account_update, keys: attributes)
end
end`
Devise User model with validations
`class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :name, presence: true
validates :password, presence: true
validates :email, presence: true
validates :roles, presence: true
has_many :reservations, dependent: :destroy
has_many :vechiles, through: :group_entities
end`
The migration file for the devise user table
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :name, null: false
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.string :current_sign_in_ip
# t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Roles col. added to user table
class AddRolesToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :roles, :text, array: true, default: []
end
end
My Routes.rb
# frozen_string_literal: true
Rails.application.routes.draw do
devise_for :users
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
resources :users, only: [:index]
# Defines the root path route ("/")
# root "articles#index"
end

can't sign in my app after mail confirmation(= response is Completed 401 Unauthorized)/ Rails / devise / devise-token-auth

I'm developing user sign in function with devise and devise-token-auth.
When I create test user record, and try to sign in, It's not working.
Server(localhost) returnd [Completed 401 Unauthorized].
I checked forrowing points.
stamped confirmed_at column
typo(password and email)
user.confirmed? => true
enviroment
Docker
ruby 2.7.2
rails (6.1.3.1)(API)
bcrypt (3.1.16)
devise (4.7.3)
devise_token_auth (1.1.5)
files
devise.rb
Devise.setup do |config|
config.mailer_sender = Rails.application.credentials.config[:smtp_settings][:user_name]
config.mailer = 'DeviseMailer'
require 'devise/orm/active_record'
config.case_insensitive_keys = [:email]
config.strip_whitespace_keys = [:email]
config.http_authenticatable_on_xhr = true
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 12
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.reset_password_within = 6.hours
config.scoped_views = true
config.sign_out_via = :delete
end
devise_token_auth.rb
DeviseTokenAuth.setup do |config|
config.change_headers_on_each_request = false
config.token_lifespan = 2.weeks
config.token_cost = Rails.env.test? ? 4 : 10
config.headers_names = {:'access-token' => 'access-token',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'uid',
:'token-type' => 'token-type' }
config.send_confirmation_email = true
config.default_confirm_success_url = 'https://example.com/login'
config.default_callbacks = false
end
routes.rb
Rails.application.routes.draw do
scope :api do
mount_devise_token_auth_for 'User', at: 'users', controllers: {
registrations: 'users/registrations',
}
resources :users, only: [:show]
end
end
application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :validatable, :lockable, :timeoutable, :rememberable, :trackable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :trackable, :confirmable
include DeviseTokenAuth::Concerns::User
migration
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[6.0]
def change
create_table(:users) do |t|
## Required
t.string :provider, :null => false, :default => "email"
t.string :uid, :null => false, :default => ""
## Database authenticatable
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
t.boolean :allow_password_change, :default => false
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email
## User Info
t.string :name
t.string :nickname
t.string :image
t.string :email
## Tokens
t.json :tokens
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, [:uid, :provider], unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
end
end

Unable to integrate lockable for number of failed attempts into Rails app

I am new to rails+angular. For my app, I want to lock out user after 5 failed password attempts. I decided to follow this:
How to make Devise lockable with number of failed attempts
But when I try logging in after 5 failed attempts, it lets me through
I added the :locked module to my user.rb (shown below) file so that the locked feature appears in devise.rb
User.rb
class User < ActiveRecord::Base
include TokenAuthenticatable
TYPE = {
:admin => 1,
:member => 2
}
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable, :token_authenticatable,
:timeoutable, :lockable ##this was added
has_and_belongs_to_many :clients
end
In my migrations then, I un-commented out the lockable part of it :
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.string :type
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end
To troubleshoot this, I also tried adding :locked, :failed_attempts => 5and uncommented out all the lockable features in initializer/devise. I am unsure on how to proceed - help would be appreciated.

NoMethodError - undefined method `email' for #<ActionDispatch::

Devise 3.5.2, Rails 4.2.3
While logging in, I'm trying to pass a hidden role_id along with the email/password combination. I am allowing the same email to register again, on a different subdomain, which causes a different role_id to be passed. The email+role_id is the unique index for the user.
I can create a user, but cannot log in. When I submit the log in form, I am faced with the following error:
undefined method 'email' for #<ActionDispatch::Request:0x007fa21628bda0>
EDIT:
If anyone can explain the process of changing the email uniqueness validation to email+role_id (not either/or, but and), that's all I need to accomplish. Following that process properly may avoid this error.
Debugging info:
The POST parameters are as follows:
{"utf8"=>"✓",
"authenticity_token"=>"[FILTERED]",
"member"=>{"role_id"=>"1",
"email"=>"some.user#email.com",
"password"=>"[FILTERED]",
"remember_me"=>"0"},
"commit"=>"Log in"}
Here is my Member model:
class Member < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable, :omniauthable
belongs_to :role
def self.find_for_authentication(warden_conditions)
where(:email => warden_conditions[:email], :role_id => warden_conditions[:role_id]).first
end
end
In config/initializers/devise.rb, the following is set:
config.authentication_keys = [:email, :role_id]
config.request_keys = [:email, :role_id]
My views/devise/sessions/new.html.erb includes:
<%= f.hidden_field :role_id, :value => Role.find_by_name(current_subdomain).id %>
I adjusted vendor/bundle/ruby/1.9.1/gems/devise-3.5.2/lib/devise/models/validatable.rb by changing this line:
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
to:
validates_uniqueness_of :email, :scope => :role_id, allow_blank: true, if: :email_changed? #using subdomains for validation
The relevant database migrations for the member are found here:
...devise_create_members.rb
class DeviseCreateMembers < ActiveRecord::Migration
def change
create_table(:members) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
t.timestamps null: false
end
add_index :members, :email, unique: true
add_index :members, :reset_password_token, unique: true
add_index :members, :confirmation_token, unique: true
add_index :members, :unlock_token, unique: true
end
...add_columns_to_member.rb
class AddColumnsToMember < ActiveRecord::Migration
def change
add_reference :members, :contact, index: true
add_reference :members, :role, index: true
add_reference :members, :ownership, index: true
add_column :members, :account_status, :string
end
end
...reindex_members_email_and_role.rb
class ReindexMembersEmailAndRole < ActiveRecord::Migration
def change
add_index :members, [:email, :role_id], :unique => true
end
end
The last item on the trace is:
vendor/bundle/ruby/1.9.1/gems/devise-3.5.2/lib/devise/strategies/authenticatable.rb:152:in `block in request_values'
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
values = keys.map { |k| self.request.send(k) } <--ERROR THIS LINE
Hash[keys.zip(values)]
end
What am I missing?
To fix this, I changed my config/initializers/devise.rb to reflect the following:
config.request_keys = { role_id: false }
This fixed the issue, but still prevented the same email from signing up with a different role ID. To fix this, I removed :validatable from my User model and added:
validates_uniqueness_of :email, :case_sensitive => false, :scope => :role_id, :allow_blank => true, :if => :email_changed?
validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed?
validates_presence_of :password, :on=>:create
validates_confirmation_of :password, :on=>:create
validates_length_of :password, :within => Devise.password_length, :allow_blank => true
This allows the same email address to sign up with a different role_id.
I also changed the following in authenticatable.rb:
def request_values
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
values = keys.map { |k| self.request[self.scope][k] }
# values = keys.map { |k| self.request.send(k) }
Hash[keys.zip(values)]
end
UPDATE
I got tired of always having to re-hack the devise library, especially after I updated gems or transferred the app. I found this page that offered a better work-around (still follow the step regarding validations the User model listed above):
(From https://github.com/plataformatec/devise/pull/3965)
Comment out the following line we edited above:
# config.request_keys = { role_id: false }
Edit the config.authentication_keys line as follows:
config.authentication_keys = { email: true, role_id: false }
The issue is that request_keys honors only predefined keys such as :subdomain.
That should work now for creating a combination of custom keys to authenticate with.

Devise: undefined method `params_authenticatable?' for User:Class

I am using devise for authentication in my rails app.
I keep getting different errors like "undefined method XXXX for User:class".
Looking for some help to setup devise correctly.
I have the module database_authenticable setup for Users and I hit the error:
undefined method `params_authenticatable?' for User:Class
Its comming from the following devise code in lib/devise/strategies/authenticatable.rb
def params_authenticatable?
mapping.to.params_authenticatable?(authenticatable_name)
end
Here are my devise settings:
class User < ActiveRecord::Base
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :trackable, :validatable , :omniauthable, :omniauth_providers => [:linkedin]
.
.
end
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end
Mu authentication requirements are straightforward and I want to use Linkedin authentication and eventually allowing other omni auths as well.
I am wondering if I should use socery or something else for simple authentication
Thanks !
I am using Rails4.0

Resources