Well, I got a problem to authenticate the user at the moment of changing his/her password, I get the mail and password and run the self.authenticate, but it keep returning me nil
I use the same format as when I log in. Here's the code
user_controller.rb
def change_pw
#user = User.authenticate(current_user.email, params[:password])
logger.info current_user.email
if #user.nil?
logger.info params[:password]
flash[:notice] = "incorrect password"
redirect_to :back
else
if #user.valid?
#user.password = #user.new_password unless #user.new_password.nil? || #user.new_password.empty?
#user.save
flash[:notice] = "Los cambios se han realizado exitosamente."
redirect_to #user
end
end
end
user.rb
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
return user
else
return nil
end
end
form
<%= form_for(#user, :url => "/change_password") do |f| %>
<%= hidden_field(:user, :email, :value => #user.email) %>
<div class="form-group">
<div class="form-group col-md-4"><%= f.label :password %></div>
<div class="form-group col-md-8"><%= f.password_field(:password, :class => "form-control") %></div>
</div>
<div class="form-group col-md-4"><%= f.label :new_password %></div>
<div class="form-group col-md-8"><%= f.password_field(:new_password, :class => "form-control") %></div>
<div class="form-group">
<div class="form-group col-md-4"><%= f.label :new_password_confirmation %></div>
<div class="form-group col-md-8"><%= f.password_field(:new_password_confirmation, :class => "form-control") %></div>
</div>
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Change Password</button>
</div>
<% end %>
I'm just trying to figure it out why it keeps returning me nil and how I can success on change password.
I finally found the reason of all my problems
def change_pw
#user = User.authenticate(current_user.email, params[:user][:password])
if #user.nil?
flash[:notice] = "ContraseƱa incorrecta"
redirect_to :back
else
if #user.valid?
#user.password = params[:user][:new_password] unless params[:user][:new_password].nil? || params[:user][:new_password].empty?
#user.save
redirect_to #user
end
end
end
There's the way to solve it, i had to specified the params directly and that's all
Related
I have a list of users that post reviews. I'm trying to make the list sortable in different ways. I'm stuck on sorting the list by each user's most recent review.
My current approach is to make a model scope. I'm just not getting it.
This is the model:
class User < ApplicationRecord
attr_accessor :password
validates_confirmation_of :password
validates :email, :presence => true, :uniqueness => true
validates :user_name, :presence => true, :uniqueness => true
before_save :encrypt_password
has_many :reviews
has_one_attached :avatar_pic
scope :users_most_recent, -> {(
select('users.id, users.user_name')
.joins(:reviews).where('reviews.updated_at')
.group('users.id')
.order('updated_at DESC')
)}
def self.user_reviews(user_id)
#user_reviews = Review.where(user_id: user_id).count
end
def self.user_ave_rating(user_id)
_average_reviews = []
_rev_count = 0
_new_average = 0.0
_average_reviews = Review.where(user_id: user_id)
_average_reviews.each do |average_review|
_rev_count += average_review.rating
end
_new_average = (_rev_count / _average_reviews.length.to_f).round(1)
end
def self.user_latest_review(user_id)
#latest_review = Review.where(user_id: user_id).where('created_at < ? ', Time.now).order('created_at DESC').first
if #latest_review.nil?
last_review = {}
else
last_review = #latest_review.created_at.strftime('%m-%d-%Y')
end
end
def encrypt_password
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password,password_salt)
end
def self.authenticate(email, password)
user = User.find_by "email = ?", email
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
end
This is the controller, the index is where I'm trying to implement this:
class UsersController < ApplicationController
before_action :current_user, only: [:show, :edit, :update, :destroy]
def new
#user = User.new
end
def create
#user = User.new(user_params)
#user.avatar_pic.attach(params[:user][:avatar_pic])
if #user.save
flash[:notice] = "You've successfully signed up!"
session[:user_id] = #user.id
redirect_to "/"
else
flash[:alert] = "There was a problem signing up."
redirect_to '/signup'
end
end
def show
#user = current_user
render :show
end
def edit
#user = current_user
render :edit
end
def update
#user = current_user
if #user.update(user_params)
flash[:notice] = "Profile successfully updated!"
redirect_to user_path(#user)
else
render :edit
flash[:notice] = "Something went wrong. Please contact Mario's technical assistance staff."
end
end
def index
case
when params[:az]
#users = User.order('user_name').paginate(page: params[:page], per_page: 20)
when params[:za]
#users = User.order('user_name DESC').paginate(page: params[:page], per_page: 20)
when params[:high_rating]
"High Rating"
when params[:low_rating]
"Low Rating"
when params[:most_reviews]
"Most Reviews"
when params[:least_reviews]
"Least Reviews"
when params[:most_recent]
#users = User.users_most_recent.paginate(page: params[:page], per_page: 20)
when params[:least_recent]
"Least Recent"
else
#users = User.all.paginate(page: params[:page], per_page: 20)
end
render :index
end
private
def user_params
params.require(:user).permit(:email, :user_name, :password, :password_confirmation, :admin, :avatar_pic)
end
end
This is my view:
<p id="notice"><%= notice %></p>
<div class="sort-flex-wrapper">
<h1 class="center">Our Community</h1>
<div class="btn-group sort-button">
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Sort By
</button>
<div class="dropdown-menu">
<%= link_to "User Name A-Z", users_path(:az => 'az'), class: "dropdown-item" %>
<%= link_to "User Name Z-A", users_path(:za => 'za'), class: "dropdown-item" %>
<%= link_to "Highest Average Rating", users_path(:high_rating => 'high_rating'), class: "dropdown-item" %>
<%= link_to "Lowest Average Rating", users_path(:low_rating => 'low_rating'), class: "dropdown-item" %>
<%= link_to "Most Reviews", users_path(:most_reviews => 'most_reviews'), class: "dropdown-item" %>
<%= link_to "Least Reviews", users_path(:least_reviews => 'least_reviews'), class: "dropdown-item" %>
<%= link_to "Most Recent Review", users_path(:most_recent => 'most_recent'), class: "dropdown-item" %>
<%= link_to "Least Recent Review", users_path(:least_recent => 'least_recent'), class: "dropdown-item" %>
</div>
</div>
</div>
<div class="community-flex-container">
<% if #users.any? %>
<% #users.each do |user| %>
<div class="community-profile-card">
<div class="community-profile-flex">
<div class="community-profile-box1">
<% if user.avatar_pic.attached? %>
<%= image_tag user.avatar_pic, class:"avatar" %><br>
<% else %>
<%= image_tag 'generc_profile_pic.webp', class:"avatar", alt: 'Avatar Not Found ' %><br>
<% end %>
</div>
<div class="community-profile-box2">
<div class="community-column-box1">
<% if user.user_name? %>
<h3><%= user.user_name %></h3>
<% else %>
<h3>Guest User</h3>
<% end %>
</div>
<div class="community-column-box2">
<div class="community-align-stars">
<p>Average Rating: </p>
</div>
<div class="community-align-stars">
<div class="star-align">
<%= render partial: "shared/review_stars", locals: { review: User.user_ave_rating(user.id) } %>
</div>
</div>
</div>
<div class="community-column-box3">
<p>Number of Reviews: <%= User.user_reviews(user.id) %></p>
</div>
<div class="community-column-box4">
<% if User.user_latest_review(user.id) == {} %>
<p>Most Recent Review: None</p>
<% else %>
<p>Most Recent Review: <%= User.user_latest_review(user.id) %></p>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
<% else %>
<p>There are no users (yet).</p>
<% end %>
</div>
<div class="pagination">
<%= will_paginate #reviews%>
</div>
scope :users_most_recent, -> {(
select('users.id, users.user_name, max(reviews.updated_at) as reviews_updated_at')
.joins(:reviews)
.group('users.id')
.order('reviews_updated_at')
)}
Well, while we're at it we might as well fix the whole index method. You're doing to much in the controller, split it out to something like this:
class UserList
def self.order_users_by(order_value)
case order_value
when :az
User.order('user_name ASC')
when :za
User.order('user_name DESC')
when :high_rating
User.all.sort_by(&:average_rating).reverse
when :low_rating
User.all.sort_by(&:average_rating)
when :most_reviews
User.all.sort_by(&:review_count).reverse
when :least_reviews
User.all.sort_by(&:review_count)
else
User.all.sort_by(&:last_updated_review)
end
end
end
class User
def average_rating
(BigDecimal(reviews.sum(:rating).to_s) / BigDecimal(reviews.count.to_s)).round(1)
end
def review_count
reviews.count
end
def last_updated_review
reviews.order("updated_at")
end
end
class UsersController < ApplicationController
def index
UserList.order_users_by(params).paginate(page: params[:page], per_page: 20)
end
end
I have a parent table and in it there is a boolean field admin. I have a admin signup page where i want a hidden field for admin to set as true. Please help. I have tried the step below. please correct it as it is not working.
<div class='row'>
<div class= 'col-xs-12'>
<%= form_for(#parent, :html => { multipart: true, class: "form-horizontal", role: "form"}) do |f| %>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= f.label :email, class: "required" %>
</div>
<div class="col-sm-8">
<%= f.email_field :email, class: "form-control", placeholder: "Enter email", required: true %>
</div>
</div>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= f.label :password, class: "required" %>
</div>
<div class="col-sm-8">
<%= f.password_field :password, class: "form-control", placeholder: "Enter password", required: true %>
</div>
</div>
<div class = "form-group">
<div class="control-label col-sm-2">
<%= f.label :password_confirmation, class: "required" %>
</div>
<div class="col-sm-8">
<%= f.password_field :password_confirmation, class: "form-control", placeholder: "Re-enter password", required: true %>
</div>
</div>
<%= f.hidden_field :admin, :value => true %>
<div class="form-group">
<div class="col-sm-10">
<%= f.submit 'Sign up', class: 'btn btn-primary btn-lg' %>
</div>
</div>
<% end %>
</div>
</div>
Parent controller
def addusers
#parent=Parent.new
end
Updated parent controller
def new
#parent = Parent.new
#parent.secondaryparents.build
add_breadcrumb "Home", :root_path
add_breadcrumb "Sign up"
end
def addusers
#parent=Parent.new
end
def create_users
#parent=Parent.new(parent_params)
#parent.admin = true
if #parent.save
ParentMailer.registration_confirmation(#parent).deliver
flash[:success] = "Please ask user to confirm email address to continue"
redirect_to main_admin_path
else
flash[:danger] = "There was an error with registering. Try again"
redirect_to main_admin_path
end
end
def create
#parent = Parent.new(parent_params)
if #parent.save
ParentMailer.registration_confirmation(#parent).deliver
flash[:success] = "Please confirm your email address to continue"
redirect_to root_path(#parent)
else
flash[:danger] = "There was an error with registering. Try again"
redirect_to signup_path
end
end
Routes
resources :parents do
resources :children do
resources :fundings
end
end
end
get 'signup', to:'parents#new'
get 'login', to: 'sessions#new'
get 'usersignup', to:'parents#addusers'
post 'usersignup', to:'parents#create_users'
resources :parents, except: [:new] do
member do
get :confirm_email
end
end
Remove hidden line from html page, no need it f.hidden_field :admin, :value => true
Form_for
form_for(#parent, url: usersignup_path,
:html => { multipart: true, class: "form-horizontal", role: "form"}) do |f|
Add to routes:
post 'usersignup', to:'parents#create_users'
Controller:
def create_users
#parent = Parent.new(parent_params)
#parent.admin = true
if #parent.save
#do yr logic here
else
redirect_back(fallback_location: "/", flash: { danger: "smth went wrong.." })
end
end
def parent_params
params.require(:parent).permit(:email, :password, :password_confirmation)
end
this is my view file i am sending the userid in parameters,
<%= form_for :user, :url=>{:action=>'update'},:method=>"get",:html=>{:class=>'form-horizontal'} do |f|%>
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">Admin</label>
<div class="col-md-4">
<%= f.radio_button :is_admin, 'true', :checked => true %> Yes
<%= f.radio_button :is_admin, 'false' %> no
<%= f.hidden_field :userid, value: #id %>
</div>
</div>
<%= f.submit ('save') %>
<% end %>
but when i try to access it in my controller i get following error (record not found):
I am finding user in my controller method like this:
def update
#users = User.all
#uid = params[:userid]
#users = User.find_by_id!(#uid)
if #users.update_attributes(user_params)
flash[:notice] = "User updated successfully."
redirect_to :action=>'view'
else
flash[:notice] = "Error while updating user."
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:is_admin,:is_member)
end
end
Instead of:
#uid = params[:userid]
Try:
#uid = params[:user][:userid]
I am setting up a form so users can add a new Stripe credit card. I receive a First argument in form cannot contain nil or be empty on the form to <%= form_for #subscription do |f| %>
What exactly am I missing so I can have the form up and submitting to Stripe?
Subscription Controller:
def new
plan = Plan.find(params[:plan_id])
#subscription = plan.subscriptions.build
if params[:PayerID]
#subscription.paypal_customer_token = params[:PayerID]
#subscription.paypal_payment_token = params[:token]
#subscription.email = #subscription.paypal.checkout_details.email
end
end
def create
#subscription = Subscription.new(params[:subscription])
if #subscription.save_with_payment
redirect_to #subscription, :notice => "Thank you for subscribing!"
else
render :new
end
end
def show
#subscription = Subscription.find(params[:id])
end
def paypal_checkout
plan = Plan.find(params[:plan_id])
subscription = plan.subscriptions.build
redirect_to subscription.paypal.checkout_url(
return_url: new_subscription_url(:plan_id => plan.id),
cancel_url: root_url
)
end
def updatesubscription
#user = current_user
#customer = Stripe::Customer.retrieve(#user.subscription.stripe_customer_token)
#customer.update_subscription(:plan => "1", :prorate => true)
current_user.save!
flash.alert = 'Your subscription has been updated!'
redirect_to root_url
end
def cancelsubscription
#user = current_user
#customer = Stripe::Customer.retrieve(#user.subscription.stripe_customer_token)
#customer.cancel_subscription()
current_user.save!
flash.alert = 'Your subscription has been cancelled successfully!'
redirect_to root_url
end
def create_card_stripe
#user = current_user
#customer = Stripe::Customer.retrieve(#user.subscription.stripe_customer_token)
#customer.cards.create({
:card => #user.subscription.stripe_customer_token
})
#user.update_attribute(:stripe_card_id, customer.active_card.id)
if customer.save
flash.alert = "Credit card updated successfully!"
redirect_to root_url
else
flash.alert = "Error with updating card"
redirect_to root_url
end
end
end
Form:
Add new Credit Card
<%= form_for #subscription do |f| %>
<% if #subscription.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#subscription.errors.count, "error") %> prohibited this subscription from being saved:</h2>
<ul>
<% #subscription.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :plan_id %>
<%= f.hidden_field :stripe_card_token %>
<div class="field">
<%= radio_button_tag :pay_with, :card, true %>
<%= label_tag :pay_with_card do %>
<%= image_tag "visa.png" %>
<%= image_tag "mastercard.png" %>
<%= image_tag "discover.png" %>
<%= image_tag "american_express.png" %>
<%= image_tag "jcb.png" %>
</div>
<% end %>
<div id="billing_fields">
<div class="field">
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<% if #subscription.payment_provided? %>
Payment has been provided. Click "Subscribe" to complete the subscription.
<% else %>
<div class="field">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_code, "Security Code on Card (CVV)" %>
<%= text_field_tag :card_code, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_month, "Card Expiration" %>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %>
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"} %>
</div>
<% end %>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
<div class="actions">
<%= f.submit "New Card" %>
</div>
</div>
<% end %>
You are getting the error because #subscription is nil.
Set the value of #subscription in the Subscription Controller's action which renders this view.
HI ,
i have some doubts on sign up feature in rails application (2.3.10)
in my views/users/new.html.erb
<div id="signup_form" style="display:none;" class="login-drpdwn ">
<% form_for :user, :url => users_path do |f| -%>
<%= error_messages_for 'user' %><br/>
<div>
<p> Enter your name </p>
<%= f.text_field :name, :class => "text_box" %>
<p> Enter your login name </p>
<%= f.text_field :login, :class => "text_box" %>
<p> Email ID</p>
<%= f.text_field :email, :class => "text_box" %>
<p> Password</p>
<%= f.password_field :password, :class => "text_box" %>
<p> Confirm your password</p>
<%= f.password_field :password_confirmation, :class => "text_box" %>
<div class="textalign_right">
<input type="submit" value="Submit" class="submit_button rounded_corner"/>
</div>
</div>
<% end %>
</div>
In my Users controller
before_filter :login_required, :except => [:new, :create, :forgot, :reset, :process_forgot_password, :activate]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to "/blogs/home",:notice => "signed up"
else
redirect_to "new"
end
end
In my User model
before_save :encrypt_password
attr_protected :id, :password_salt
attr_accessor :password, :password_confirmation
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
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
In my sessions controller - create method
def create
#current_user = User.find_by_login(params[:login].downcase)
if #current_user.blank? || params[:password] != #current_user.password_hash
#current_user = nil
render :action => "new"
else
session[:user_id] = #current_user.id
session[:close_time] = 1800.seconds.from_now
if #current_user.last_login.nil?
#login = LastLogin.new
#login.user_id = #current_user.id
#login.login_at = Time.now
#login.save
else
#login = #current_user.last_login
#login.last_at = #login.login_at
#login.login_at = Time.now
#login.login_count += 1
#login.save
end
if session[:return_to]
redirect_to session[:return_to], :protocol => USE_PROTOCOL
session[:return_to] = nil
else
end
end
end
when i submit the sign up page the user is getting created but not the session
so its not directing to the blogs /home page as it has before_filter :login_required there in blogs controller..
how to resolve this
My code is not having include Authenticated system line
session[:id] = #current_user.id