session not working in post method in rails - ruby-on-rails

session[:user_id] = user.id this session not working but its working in get method(login)
# Working fine here
# get 'users/login'=>'users#login'
def login
session[:user_id] = 1
end
# post 'users/auth'=>'users#loginpost'
def loginpost
user = User.authenticate(request.POST['name'], request.POST['password'])
if user
# But not working here:(
session[:user_id] = user.id
redirect_to root_url, :notice => "You are Successfully logged in ^^"
else
render html: '<strong>HTML String</strong>'
#render users_login_url, :notice => "You are entered invalid email or password"
end
end

Related

rails 4 - role based authorization from scratch

I have recently started learning rails and had to develop an application with three roles: user(admin), student, instructor. I wrote the following code myself. but the problem is that it makes the role of all active users similar to the most recent login. For example, if admin was logged in and later a student logs in and then if admin refreshes her page, she will also become a student. What i should change in my code to fix this problem? And if it is not possible to implement it like this way, suggest me how i should fix this problem. thanks.
here is my users_controller code:
def login
if session[:user_id]!=nil
redirect_to(:action => 'index')
end
end
def attempt_login
if params[:username].present? && params[:password].present?
found_user = User.where(:username => params[:username]).first
if found_user
authorized_user = found_user.authenticate(params[:password])
if authorized_user
flash[:notice] = "Welcome! You are LoggedIn"
session[:user_id] = authorized_user.id
redirect_to(:action => 'index')
return
end
end
found_student = Student.where(:username => params[:username]).first
if found_student
student_id = Student.authenticate( params[:username],params[:password])
if student_id
flash[:notice] = "Welcome! You are LoggedIn"
session[:user_id] = student_id
redirect_to(:action => 'student_index')
return
end
end
found_instructor = Instructor.where(:username => params[:username]).first
if found_instructor
instructor_id = Instructor.authenticate( params[:username],params[:password])
if instructor_id
flash[:notice] = "Welcome! You are LoggedIn"
session[:user_id] = instructor_id
redirect_to(:action => 'instructor_index')
return
end
end
flash[:notice] = "Invalid username/Password combination."
redirect_to(:action => 'login')
end
end
def logout
flash[:notice]="Logged out"
session[:user_id] = nil
redirect_to(:action => "login")
end
and here is my application_controller.rb code
def require_login
unless session[:user_id] or config.my_config
flash[:notice] = "You are not Logged In"
redirect_to :root
return false
else
return true
end
end
It seems to me that you're sharing the same session key session[:user_id] to store the ID of User, Student and Instructor. How do you differentiate between the three kinds of logged in users?
It's possible that if a logged in Student visits the instructor_index path, then the student's ID would be used to load a Instructor with the same ID, and a view for an instructor would be rendered. I don't see any code to indicate otherwise.
I would have expected such a system to store both a session[:user_id], and a session[:user_type] to ensure that it's possible to exactly identify the logged in person.

redirect_to is not working when testing my action using Rspec

I'm testing an action but I can't make it pass.
My spec:
it 'redirects to the datatables page for authenticated users' do
user = User.create(name: 'fer', email: 'fer#fer.fer', password: 'fer')
session[:user_id] = user.id
get :new
expect(response).to redirect_to datatables_lists_path
end
My code:
def create
user = User.where(email: params[:email]).first
if user && user.authenticate(params[:password] )
session[:user_id] = user.id
redirect_to datatables_lists_path, notice: 'you are in!! :)'
else
flash[:error] = 'it's not working'
redirect_to sign_in_path
end
end
The message I'm getting is:
1) SessionsController redirects to the datatables page for authenticated users
Failure/Error: expect(response).to redirect_to datatables_lists_path
Expected response to be a <redirect>, but was <200>
You're issuing a get :new and yet you're showing us the create action from your controller. Your test isn't testing the create action.

Rails: Notice error

While trying to follow a tutorial, I raised an error when I test the "Sign out" link. I checked the difference with the tutor, but I couldn't figure out why I can't do it my way and why the error occurs on this spot.
My code:
class SessionsController < ApplicationController
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
redirect_to(session[:intended_url] || user), notice:"Welcome back, #{user.name}"
session[:intended_url] = nil
else
flash.now[:alert] = "Invalid email/password combination! you are a failure"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "You're now signed out!"
end
end
The correction code:
class SessionsController < ApplicationController
def new
end
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
flash[:notice] = "Welcome back, #{user.name}!"
redirect_to(session[:intended_url] || user)
session[:intended_url] = nil
else
flash.now[:alert] = "Invalid email/password combination!"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "You're now signed out!"
end
end
The error that was raised:
SyntaxError in SessionsController#destroy
C:/Users/xcpro/ve2/2B3/app/controllers/sessions_controller.rb:6:
syntax error, unexpected ',', expecting keyword_end
...ession[:intended_url] || user), notice:"Welcome back, #{user... ...
^
The problem is that method redirect_to take parameters only in parentheses, however notice also should passed in it. Add parentheses around all redirect_to parameters:
redirect_to( (session[:intended_url] || user), notice: "Welcome back, #{user.name}" )
or maybe space after redirect_to would work also:
redirect_to (session[:intended_url] || user), notice: "Welcome back, #{user.name}"

Devise and Omniauth

I'm trying to integrate Devise with Omniauth and have some troubles with them both. The main problem is to bind Devise User model with Omniauth authentications. I want a simple way to associate my user, with external providers like facebook, twitter, g+ and so on.
One of the most annoying issues that arise with my application is:
If an user registered on my site with devise (I call it local user), that means, provided an email and a password, when user tries to login with twitter, the system asks for mail confirmation. If that mail already exists, then user have to provide another mail. I want instead that he can confirm with a password that it is actually his email. How to do that? How can I override that template?
This is my authentications controller:
class AuthenticationsController < ApplicationController
def index
#authentications = Authentication.all
end
def create
#authentication = Authentication.new(params[:authentication])
if #authentication.save
redirect_to authentications_url, :notice => "Successfully created authentication."
else
render :action => 'new'
end
end
def destroy
#authentication = Authentication.find(params[:id])
#authentication.destroy
redirect_to authentications_url, :notice => "Successfully destroyed authentication."
end
def twitter
omni = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omni['provider'], omni['uid'])
if authentication
flash[:notice] = "Logged in Successfully"
sign_in_and_redirect User.find(authentication.user_id)
elsif current_user
token = omni['credentials'].token
token_secret = omni['credentials'].secret
current_user.authentications.create!(:provider => omni['provider'], :uid => omni['uid'], :token => token, :token_secret => token_secret)
flash[:notice] = "Authentication successful."
sign_in_and_redirect current_user
else
user = User.new
user.apply_omniauth(omni)
if user.save
flash[:notice] = "Logged in."
sign_in_and_redirect User.find(user.id)
else
session[:omniauth] = omni.except('extra')
p session
redirect_to new_user_registration_path
end
end
end
end
I also have no idea where new_users_registration_path is.

User Authentication: Providing separate errors for invalid email/password entry

In my Rails app I'm trying to produce a separate flash.now[:alert] for invalid :email and :password, respectively. So if a user enters the correct email but wrong password, the :alert warns the user of an invalid password and vice versa. Here's what I have in my SessionsController:
def create
if user = User.authenticate(params[:email], params[:password])
session[:user_id] = user.id
redirect_to user.profile, :notice => "Logged in successfully"
elsif user.email != params[:email]
session[:email] = #user.email
flash.now[:alert] = "Invalid email. Try again!"
render :action => 'new'
else
session[:password] = #user.password
flash.now[:alert] = "Invalid password. Try again!"
render :action => 'new'
end
end
Rendering this gives me an undefined method for email. Can anyone help me figure out what I'm doing wrong?
DISCLAIMER: Obviously this is a really bad idea as an attacker could keep on trying emails until he found one that did match and then he could start trying passwords for this email he knows exists at your database, but you're asking, so it's up to you deciding to do this or not.
Your authenticate method obviously only returns the user if the email and password did match, change your authenticate method to return a boolean and a user if there is any available. It would look somewhat like this:
def authenticate(email, password)
u = first(:conditions => {:email => email, :state => 'active'})
u && u.authenticated?(password) ? [true, u] : [false, u]
end
Then, at your controller:
def create
result , user = User.authenticate(params[:email], params[:password])
if result
session[:user_id] = user.id
redirect_to user.profile, :notice => "Logged in successfully"
elsif user
session[:email] = #user.email
flash.now[:alert] = "Invalid email. Try again!"
render :action => 'new'
else
session[:password] = #user.password
flash.now[:alert] = "Invalid password. Try again!"
render :action => 'new'
end
end
And this should work.

Resources