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
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
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
I am working on a project and I need to do a password reset system.
I'm not using any gem.
mailers/password_reset.rb
class PasswordReset < ActionMailer::Base
default from: 'no-reply#educx.com'
def send_password_reset(user)
#user = user
#reset_link = edit_password_resets_url({
token: #user.password_reset_token
})
mail({
:to => user.email,
:bcc => ['reset password <resetpassword#educx.com'],
:subject => I18n.t('password_reset.send_password_reset.subject')
})
end
end
views/password_reset/send_password_reset.html.erb
<h2><%= t '.greetings', full_name: #user.full_name %></h2>
<p><%= t '.body_html', link: link_to(t('.click_here'), #reset_link) %></p>
controllers/password_resets_controller.rb
class PasswordResetsController < ApplicationController
before_action :require_no_authentication, only: [:new, :create, :edit, :update]
def new
end
def create
user = User.find_by(email: params[:email])
if user.present?
user.generate_password_reset
PasswordReset.send_password_reset(user).deliver
redirect_to root_url, notice: t('flash.notice.check_email_reset')
else
flash[:alert] = t('flash.alert.cannot_find_email_reset')
render :new
end
end
def edit
#user = User.find_by(password_reset_token: params[:token])
end
def update
#user = User.find_by!(password_reset_token: params[:token])
if #user.password_reset_sent_at < 2.hours.ago
redirect_to new_password_reset_path, alert: t('flash.alert.time_expired')
end
if #user.update(password_reset_user_params)
#user.password_reseted!
redirect_to new_user_sessions_path, notice: t('flash.notice.password_reseted_complete')
else
render :edit
end
end
private
def password_reset_user_params
params.require(:user).permit(:password, :password_confirmation)
end
end
models/user.rb
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
VALID_BIRTHDAY_REGEX = /[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/
validates_presence_of :full_name, :email, :birthday, :about
validates_length_of :about, minimum: 10, maximum: 100
validates_format_of :email, with: VALID_EMAIL_REGEX
validates_uniqueness_of :email
validates_format_of :birthday, with: VALID_BIRTHDAY_REGEX
has_secure_password
scope :confirmed, -> { where.not(created_at: nil) }
before_create do |user|
user.confirmation_token = SecureRandom.urlsafe_base64
end
def confirm!
return if confirmed?
self.confirmed_at = Time.current
self.confirmation_token = ''
save!
end
def confirmed?
confirmed_at.present?
end
def self.authenticate(email, password)
user = confirmed.find_by(email: email)
if user.present?
user.authenticate(password)
end
end
def generate_password_reset
self.password_reset_token = SecureRandom.urlsafe_base64
self.password_reset_sent_at = Time.zone.now
save!
end
def password_reseted?
password_reset_token.present?
end
def password_reseted!
return if password_reseted?
self.password_reset_token = ''
self.password_reseted_at = Time.current
save!
end
def password_reseted_expired?
password_reset_sent_at < 1.hours.ago
end
end
views/password_resets/new.html.erb
<%= form_tag password_resets_path, :method => :post do %>
<div>
<%= label_tag :email %>
<%= text_field_tag :email, params[:email] %>
</div>
<div><%= submit_tag %></div>
views/password_resets/edit.html.erb
<%= form_for #user do |f| %>
<p>
<%= f.label :password %><br>
<%= f.password_field :password %>
<%= error_field(#user, :password) %>
</p>
<p>
<%= f.label :password_confirmation %><br>
<%= f.password_field :password_confirmation %>
<%= error_field(#user, :password_confirmation) %>
</p>
<p>
<%= f.submit %>
</p>
controllers/users_controller.rb
class UsersController < ApplicationController
before_action :can_change, only: [:edit, :update]
before_action :require_no_authentication, only: [:new, :create]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
Signup.confirm_email(#user).deliver
redirect_to new_user_sessions_path, notice: t('flash.notice.user_created')
else
render action: :new
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
flash[:notice] = t('flash.notice.user_updated')
redirect_to #user
else
render action: :edit
end
end
private
def user_params
params.require(:user).permit(:full_name, :email, :birthday, :password, :password_confirmation, :about)
end
def can_change
unless user_signed_in? && current_user == user
redirect_to user_path(params[:id])
end
end
def user
#user ||= User.find(params[:id])
end
end
config/routes
resource :password_resets
The email is sent with no errors. But when I click on "Edit Password" at /password_resets/edit?token=fewgfeggrf, I am redirected to user's perfil! How can I change that?
I have a controller in a rails app whereby a user can create a holiday request, it seems that when I fill out the necessary information it is not doing the POST request and submitting my form. My output in the RailsPanel follows: Rails Panel. From this its as if it is doing the GET request when surely on it should do a GET then a POST. I believe I have messed up somewhere around my create method. Any feedback would be great thank you!
controller
class HolidaysController < ApplicationController
before_filter :authenticate_user!
before_filter :admin_user, :only => [:index, :update, :edit, :absence]
before_filter :correct_user, :only => [:delete]
def new
#holiday = Holiday.new
#user = current_user
end
def show
#holiday = Holiday.find(params[:id])
c_u = current_user
end
def create
#user = current_user
#holiday = current.holidays.build(params[:holiday])
#holiday.approver_id = approval_method(current_user, #holiday)
if #holiday.save
redirect_to root_path
flash[:success]= "holiday application sent!"
else
render :new
end
end
def myholidays
#holidays = current_user.holidays.all
end
def index
#holidays = Holiday.all
end
def absence
#show the holidays where the approver id matches the current user id
#and state = "requested"'
#user = current_user
if current_user.role? :administrator
# a admin can view all current holiday requests
#holidays = Holiday.all( :conditions => 'state = "requested"')
else
#otherwise an admin sees the holiday requests that they are approvers for
#holidays = Holiday.all(:conditions => ["approver_id = #{current_user.id}", "state = requested"])
end
end
def edit
today = Date.today
#holidays = Holiday.all
#month = (params[:month] || (Time.zone || Time).now.month).to_i
#year = (params[:year] || (Time.zone || Time).now.year).to_i
#shown_month = Date.civil(#year, #month)
#L51 - Parses the given representation of date and time with the given template
#and returns a hash of parsed elements.
#holiday = Holiday.find(params[:id])
end
def update
admin = User.find(current_user.role? :administrator)
holiday = Holiday.find(params[:id])
user = User.find(id = holiday.user_id)
if holiday.update_attributes(params[:holiday])
if holiday.state == "approved"
user.absentdays = user.absentdays - (holiday.days_used).to_i
user.save
end
redirect_to absence_path, :notice => "Request updated"
else
render 'edit'
end
end
def destroy
Holiday.find(params[:id]).destroy
redirect_to root_url, :notice => "Request deleted"
end
private
def current_user?(user)
user == current_user
end
def admin_user
redirect_to dashboard_path, :notice => "You must be an admin to do this!" unless current_user.role? :administrator
end
def signed_in_user
redirect_to login_path, notice: "Please sign in." unless signed_in?
end
def correct_user
#user = current_user
redirect_to dashboard, notice: "You are not the correct user." unless current_user?(#user) or current_user.role? :administrator
end
def approval_method(current_user, holiday_to_approve)
found = false
days = holiday_to_approve.days_used
user = current_user
approver = user.role? :administrator
until found == true
#Admins should be automatically approved and have no approvers
if approver == nil
holiday_to_approve.state = "approved"
#if user absent days is equal to absent days - day and convert to integer
user.absentdays = user.absentdays - (days).to_i
user.save
found = true
else
redirect_to dashboard_path, :notice => "Request complete"
end
break if found == true
end
end
end
holidays/show.html.erb
<form class="form">
<p>You have<b><%= #user.absentdays %> days of holiday left.</b></p>
<%= form_for #holiday do |f| %>
<% if #holiday.errors.any? %>
<div>
<h2>Form is invalid</h2>
<ul>
<% for message in #holiday.error.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
Select the dates required for absence<br>
Start: <%= datepicker_input "holiday", "start_at", :minDate => 0, :dateFormat => "yy-mm-dd" %><br>
End: <%= datepicker_input "holiday", "end_at", :minDate => 0, :dateFormat => "yy-mm-dd" %>
<br><br>
Please select the type of absence you require<br>
<%= f.collection_select :type_id, Type.all, :id, :name, :prompt => "Select absence type" %>
<br><br>
<%= f.text_field :description %>
<br><br>
<%= f.submit "Submit Request", :class => "submit" %>
<% end %>
</form>
new.html.erb
<% provide(:title, 'apply for absence') %>
<p>You have <b><%= #user.absentdays %></b> days of holiday time left.</p>
<%= form_for #holiday do |f| %>
<% if #holiday.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% for message in #holiday.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
Select the dates required for absence<br>
start: <%= datepicker_input "holiday","start_at", :minDate => 0, :dateFormat => "yy-mm-dd" %><br>
end: <%= datepicker_input "holiday","end_at", :minDate => 0, :dateFormat => "yy-mm-dd" %>
<br><br>
Please select the type of absence you require<br>
<%= f.collection_select :type_id, Type.all, :id, :name, :prompt => "Select absence type" %>
<br><br>
Please provide a short description of the nature of your absence (if applicable)<br>
<%= f.text_field :description %>
<br><br>
<%= f.submit "submit" %>
<% end %>
</div>
The reason is, you are having a form in your holidays/show.html.erb but not in your holidays/new.html.erb.
According to rails convention, if form is submitted in new.html.erb, then by default the POST method is called of that particular controller.
But since your file is show.html.erb, you have to explicitly define your POST method in the form_for.
form_for #holiday , :url => { :action => :create }, :html => { :method => "post"} do |f|
i can't authenticate the Transaction_Id where this is the primary key of my transaction table, while i can do it with the email. what would seem to be the problem? help. thanks.
here's my model/transaction:
def self.authenticate(email, transaction_id)
user = Transaction.find_by_email(email)
if user && user.Transaction_Id
return user
else
return false
end
end
here's my controller/modifications:
def attempt_login
user = Transaction.authenticate(params[:email], params[:Transaction_Id])
if user
session[:user_id] = user.id
session[:email] = user.email
flash[:notice] = "You are now logged in!"
redirect_to :action => "modify"
else
flash[:notice] = "Invalid username/password combination."
redirect_to :action => "login"
end
end
and here's my view/login:
<div class="login">
<%= form_tag :action => "attempt_login" do %>
<%= label_tag :email, "Email Address:" %>
<%= text_field_tag :email %>
<%= label_tag :Transaction_Id, "Transaction Id:" %>
<%= text_field_tag :Transaction_Id %>
<%= submit_tag "Log In"%>
<% end %>
</div>
You check only if there is a transaction_id present in your found user object, but you do not compare this id to the given id, so try:
def self.authenticate(email, transaction_id)
user = Transaction.find_by_email(email)
if user && user.Transaction_Id == transaction_id
return user
else
return false
end
end
or (don't know if it works)
def self.authenticate(email, transaction_id)
user = Transaction.find_by_email_and_transaction_id(email, transaction_id)
if user
return user
else
return false
end
end
in short:
# will return user if found; else nil
def self.authenticate(email, transaction_id)
Transaction.find_by_email_and_transaction_id(email, transaction_id)
end