I am using devise for user in my rails application
When i click on forgot password than it send mail to user for reset password instruction.
but when i click on that password reset link in mail it redirect to my custom user controller which i create for user edit profile...
how to call devise password edit method
below is my controller/users.
class UsersController < ApplicationController
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:notice] = "Profile successfully updated"
redirect_to authenticated_root_path
else
render 'edit'
end
end
def change_password
#user = User.find(current_user.id)
end
private
def user_params
params.require(:user).permit(:email, :first_name, :last_name,
:dob, :address, :zip_code, :about_me, :country_id, :state_id,
:city_id, :phone_no, :status, :profile_pic, :gender,
:password, :password_confirmation)
end
end
Use this path for password reset for devise:
edit_user_registration_path
Related
One thing that confuses me the most is when doing validation in one model with two controllers. I have a login system which register and logs users in. There both use the same model but both does not use the same amount of HTML widgets. One controller contains password, retype password, user name, first & second name and so on. The second controller uses only the user name and password fields. How would you do validation in the same model for this situation?
Thank you
here is the controller that register new users:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to '/cool'
else
#user = Newuser.new
#user.valid?
#user.errors.messages
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :salt, :firstname, :secondname, :address, :postcode)
end
end
second controller:
class LoginsController < ApplicationController
before_filter :authorize
def index
#rentals = Rental.where(user_id: current_user.id).limit(5)
#buys = Buy.where(user_id: current_user.id).limit(5)
#users = User.where(id: current_user.id)
#buyGames = BuyGame.where(user_id: current_user.id).limit(5)
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to '/logout'
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(account_params)
redirect_to '/cool'
else
render 'edit'
end
end
private
def account_params
params.require(:user).permit(:name, :email, :password, :salt, :firstname, :secondname, :address, :postcode)
end
end
Here is my model:
class User < ApplicationRecord
has_secure_password
end
One way to go is to remove validations from the model and put them in form objects. For this case, you'll have two form objects, each with its own set of validations. And you use the appropriate one in respective controllers. Something along these lines:
# logins_controller
def update
login_form = FormObjects::LoginForm.new(login_params)
if login_form.valid?
redirect_to '/cool'
else
render 'edit'
end
end
# users controller
def create
signup_form = FormObjects::SignupForm.new(user_params)
if signup_form.save
redirect_to '/cool'
else
render 'new'
end
end
# signup_form
module FormObjects
class SignupForm
include ::ActiveMode::Model
validate_presense_of :email, :password, :password_confirmation, :address, :whatever_else
def save
# create user here
end
end
end
# login_form
module FormObjects
class LoginForm
include ::ActiveMode::Model
validate_presense_of :email, :password
end
end
You can simply specify validations on actions, that is:
validates :first_name, presence: true, on: :create # which won't validate presence of first name on update or any other action
I believe the trick you are looking for is to define validation actions on create/update of the model. Something roughly along these lines:
class User < ActiveRecord::Base
# These are example validations only; replace with your actual rules.
validates :password, confirmation: true
validates_presence_of :username
validates :first_name, presence: true, format: {with: /.../}, on: create
validates :last_name, presence: true, format: {with: /.../}, on: create
end
...However, I am unclear why you would want to do this in your specific example. It would be advisable to always run all validation checks on fields like first_name, to help maintain data integrity.
While creating an active admin record, am trying to save an attribute (role_type) which does not come from params.
However, the attribute does not get saved in creation.
I have added it to permit_params.
permit_params :email, :password, :password_confirmation, :phone_no, :name, :role_type, role_ids: []
controller do
def create
user = User.create(name: params[:user][:name], email: params[:user][:email], password: SecureRandom.hex, role_type: "employee")
flash[:notice] = "User Created"
redirect_to admin_user_path(user)
end
end
If you want to combine a params hash with some attributes that you assign manually the cleanest way is by using a block
permit_params :email, :password, :password_confirmation, :phone_no, :name, :role_type, role_ids: []
controller do
def create
user = User.create(permitted_params[:user]) do |u|
u.password = SecureRandom.hex
end
flash[:notice] = "User Created"
redirect_to admin_user_path(user)
end
end
However your password encryption scheme is very naive - I would recommend you use ActiveModel::SecurePassword instead of trying to reinvent the password encryption wheel and creating a insecure authentication system.
Another major issue is that you are not actually checking if the user is created!
permit_params :email, :password, :password_confirmation, :phone_no, :name, :role_type, role_ids: []
controller do
def create
user = User.new(permitted_params[:user]) do |u|
u.password = SecureRandom.hex
end
if user.save
flash[:notice] = "User Created"
redirect_to admin_user_path(user)
else
render :new
end
end
end
I have a users_controller and a user_steps_controller which has three steps :business, :payment and :login
In the user.rb model
class User < ActiveRecord::Base
validates_presence_of :fname, :lname, :email, :mob, :country, :state, :suburb, :postal ,:add
end
while checking validation if i put some random values then also it is giving errors
Fname can't be blank
Lname can't be blank
Email can't be blank
Mob can't be blank
Country can't be blank
State can't be blank
Suburb can't be blank
Postal can't be blank
Add can't be blank
Please help me out
This is my users_controller
def new
#user = User.new
end
def create
#user = User.new(params[:id])
if #user.save
session[:user_id]= #user.id
#user.update_attributes(user_params )
redirect_to user_steps_path
else
render :new
end
end
private
def user_params
params.require(:user).permit( :fname, :lname, :email, :mob, :gender_male, :gender_female, :country, :state, :suburb, :postal ,:add, :cmpyname, :abnacn, :cmpyadd, :cmpydet,:cash, :paypal,:bsb,:usrname,:password_hash, :password_salt, :selcat, :protit, :prodes)
end
user.rb
class User < ActiveRecord::Base
validates :fname, :lname, :email, :mob, :country, :state, :suburb, :postal ,:add, :presence => true
attr_accessor :current_step
validates_presence_of :cmpyname, :abnacn, :cmpyadd, :cmpydet, if: -> { current_step?(:business) }
validates_presence_of :usrname,:password_hash, :password_salt, :selcat, :protit, :prodes, if: -> { current_step?(:login) }
def current_step?(step_key)
current_step == step_key
end
end
user_steps_controller
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :business, :login, :payment
def show
#user = current_user
render_wizard
end
def update
#user = current_user
params[:user][:current_step] = step
#user.update_attributes(user_params )
render_wizard #user
end
private
def user_params
params.require(:user).permit( :cmpyname, :abnacn, :cmpyadd, :cmpydet,:cash, :paypal,:bsb,:usrname,:password_hash, :password_salt, :selcat, :protit, :prodes)
end
end
user.rb
def current_step?(step_key)
current_step == step_key
end
user_steps_controller.rb
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :personal, :social
def show
#user = current_user
render_wizard
end
def update
#user = current_user
params[:user][:current_step] = step
#user.attributes = user_params
render_wizard #user
end
private
def redirect_to_finish_wizard(options = nil)
redirect_to root_url, notice: "Thank you for signing up."
end
def user_params
params.require(:user).permit(:name, :current_step, :date_of_birth, :bio, :twitter_username, :github_username, :website)
end
end
This method will work for you.
Your real problem is here:
#user = User.new(params[:id])
I'm assuming params[:id] is nil, because otherwise that would fail. Basically, your instantiating a User with no data supplied and trying to save it. So clearly those validations you have supplied will fail. If you're actually submitting a form with user data you need to pass user_params you've already defined as follows:
#user = User.new(user_params)
If you need to have validations occur on your User model in different steps, you'll need to have the validations run conditionally dependent on the state of the form:
class User
attr_accessor :current_step
validates_presence_of :business_related_attr, if: -> { current_step?(:business) }
def current_step?(step_key)
current_step.blank? || current_step == step_key
end
end
In Rails 3 it worked just fine, but with my new Rails4 Appp i don't know whats the problem.
The Guide on the Devise GitHub Page
My Registrations Controller
def update
# required for settings form to submit when password is left blank
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
end
#user = User.find(current_user.id)
if #user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
else
render "edit"
end
end
My Application Controller
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:name, :first_name, :user_name, :email, :password, :password_confirmation, :provider, :uid)
end
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:name, :email, :password, :password_confirmation, :first_name, :last_name,
:user_name, :avatar, :profile_cover, :facebook_link,
:twitter_link, :instagram_link, :status)
end
end
I added the controller to my Routes
:registrations => "registrations"
And i Changed the update calls using the appropriate method below:
#user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
But i'm getting a NoMethodError in RegistrationsController#update Error.
I don't know yet if this is a good practice but i changed in my RegistrationsController the update action to
#user.update_attributes(account_update_params)
I am trying to make simple authentication/registration ruby app. I am using BCrypt gem for crypting and it now gives me some problems. When I press submit button it throws
undefined method `password_salt=' for #<User:0x007f93c36bc570>
Ok, so I red that this code should be places from model to coontroler, but that gave me this er
undefined local variable or method `encrypt_password' for #<User:0x007f93c5f35f10>
I have tried rake db:migrate and restarting app also
git repo: https://github.com/pumpurs/auth
(code im talking about)
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user].permit(:password, :email, :password_confirmation))
if #user.save
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
end
private
def user_params
params.require(:user).permit(:password, :email, :password_confirmation)
end
end
model file:
class User < ActiveRecord::Base
attr_accessor :password, :salt
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
Add
attr_accessor :password_salt
in model?
Why don't use Devise or another authentication gem?