Authlogic with OAuth and OpenID - DoubleRenderError - ruby-on-rails

I have authlogic and openid working correctly, and am trying to integrate oauth for twitter authentication. I do not want both a register and sign on button, so I have followed this example: Implicit user creation with Authlogic and Authlogic OAuth plugin
I get the DoubleRenderError on initial registration and subsequent log in, but refreshing the page lets the action complete successfully.
My users_controller create:
def create
#user = User.new(params[:user])
#user.save do |result| # LINE A
if result
flash[:notice] = "Account registered!"
redirect_to account_url
else
unless #user.oauth_token.nil?
#user = User.find_by_oauth_token(#user.oauth_token)
unless #user.nil?
UserSession.create(#user)
flash.now[:message] = "Welcome back!"
redirect_to account_url
else
redirect_back_or_default root_path
end
else
redirect_back_or_default root_path
end
end
end
end
And my user_sessions_controller create:
def create
#user_session = UserSession.new(params[:user_session])
#user_session.save do |result|
if result
flash[:notice] = "Login successful!"
redirect_back_or_default account_url
else
render :action => :new
end
end
end
Is there a way to resolve this? Thanks

After repeated failures, the following appears to work for normal authlogic username/password, OAuth with Twitter, and OpenID for at least google and yahoo, which is all I was interested in
def create
#user = User.new(params[:user])
#user.save do |result| # LINE A
if result
flash[:notice] = "Account registered!"
redirect_to account_url and return
else
if #user.oauth_token
#user = User.find_by_oauth_token(#user.oauth_token)
UserSession.create(#user)
flash.now[:message] = "Welcome back!"
redirect_to account_url and return
else
flash[:notice] = "Something went awry. Perhaps the name or email is already in use."
redirect_to register_path and return
end
end
end
end
Additionally, i added 'and return' into the update block in my users controller after both success and failure redirects/renders

Related

I would like to render the same page if new user is not save

I would like to render on the same page if email is blank. However, when I leave in blank instead of staying on users/new. It goes to /users. It is still render to _from for the URL is different.
def new
respond_with(user)
end
def create
if user.save
user.send_invitation
redirect_to root_url, notice: "Signed up!"
else
render "/users/new"
end
end
def destroy
#user = User.find(params[:id])
if #user.destroy
redirect_to root_url, notice: "User was deleted successfully!"
end
end
def edit
respond_with(user)
end
def update
params[:user].delete(:password) if params[:user][:password].blank?
params[:user].delete(:password_confirmation) if params[:user][:password_confirmation].blank?
if user.save
redirect_to users_path, :notice => "Saved your updates!"
else
render :edit
end
end
render "/users/new"
Just renders template users/new, at create action. So the URL stays /users.
You can try to
def create
if user.save
user.send_invitation
redirect_to root_url, notice: "Signed up!"
else
redirect_to new_user_path
end
end
But then you will have no access to submitted params, so the form will be clear.
The thing in here I think it's a routes problem, as you want to persist the URL.
What Rails does in this cases is it goes to the create action once the form was submitted and if for some reason the record is not being save(in this case) you are rendering the new action but with the object which has errors and data.
To clean up a little bit you could do something like:
def create
if user.save
user.send_invitation
redirect_to root_url, notice: "Signed up!"
else
render :new
end
end
In my opinion, don't try to bend Rails this way, you'll get a lot of problems with it and also, does it really matters to persist the URL?
Redirection is not an option, because you'll loose all the data from the request, as it would become a new request due to the redirect.
Hope this helped!

How to avoid saving after create? Rails

def create
#user = User.create(user_params)
if #user.valid?
charge = StripeWrapper::Charge.create(amount: 999, card: params[:stripeToken], description: "Sign up charge for #{#user.email}" )
if charge.successful?
#user.save
User.inviter_and_invited_follow_each_other(#user)
AppMailer.delay.welcome(current_user)
session[:user_id] = #user.id
flash[:notice] = "You have successfully registered and will be logged in."
redirect_to root_path
else
flash[:notice] = charge.error_message
render :new
end
else
render :new
end
end
User saves even when charge.successful? returns false. Nothing else happens as in no email is sent, session[:user_id] isn't set nor is it redirected to root_path. Else block executes and renders :new and displays a flash notice saying card is declined.
I am trying to avoid the user creation if charge.successful? returns false. Any idea on how to go about this?
The create method is basically a combination of doing #user = User.new followed by #user.save.
So you can just use .new instead of .create. That way, it'll only be persisted to the database when you call .save:
#user = User.new(user_params)

using redirect and if multiple times

My question is actually fairly simple, how do I make a create action which checks if a user is logged in, and if she/he is then redirect to the dashboard instead of rendering the index page where they've got links and stuff to go to and sign up. Also why is the code below not working.
class UsersController < ApplicationController
def new
#user = User.new
end
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
end
Your code isn't doing what you expect because the if statements are actually nested (you want elsif with this same structure -- or see my suggested fix below). Here's what your code, when properly formatted, actually looks like:
def create
if current_user.nil?
redirect_to dplace_index_path
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end
end
end
Logically, you will never get down into the second if statement, because current_user must be nil to enter the first. Try something like this instead:
def create
if current_user
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
else
redirect_to dplace_index_path
end
end
I rearranged the code, but it should logically do what you want now. I put the "happy path" first (the current_user exists), and moved the redirect into the else statement.
General user authentication:
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to dashboard_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
Try:
def create
if current_user.blank? # .blank? will check both blank and nil
# logic when user is not logged in
redirect_to index_path
else
# logic when user is logged in
redirect_to dashboard_path
end
end
def create
redirect_to dplace_index_path unless current_user
# no need to check current_user again
#user = User.new(params[:user])
if #user.save
auto_login(#user)
redirect_to dplace_index_path
end
end

Rails redirections with new users and logins

So I'm trying to get the user to return to the page they were looking at before they click "log in"
This is what I got in my user application controller:
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
And this is what I have in my sessions controller:
def new
#user_session = UserSession.new
session[:return_to] = request.referer
end
end
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default(home_path)
else
render :action => :new
end
end
This works fine most of the time but if a user logs in right after they register to the site, they will get redirected to a blank page. I imagine this is the "create" action because it was the last action before going to user sessions new.
So I tried this:
def new
#user_session = UserSession.new
unless request.referer == join_path
session[:return_to] = request.referer
end
end
And this tries to take me back to the login page after I log in.
What I'd really like to do is have the user see their profile when they log in for the very first time.
This wouldn't give me a user id and raised a routing error
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default(user_path(current_user))
else
render :action => :new
end
end
Anybody gone through these redirecting acrobatics before? I can't seem to get it to work. I'm using authlogic if that helps.
Found a great solution at: http://ethilien.net/archives/better-redirects-in-rails/

Authentication Problem - not recognizing 'else' - Ruby on rails

I can't seem to figure out what I am doing wrong here. I have implemented the Super Simple Authentication from Ryan Bates tutorial and while the login portion is functioning correctly, I can't get an error message and redirect to happen correctly for a bad login.
Ryan Bates admits in his comments he left this out but can't seem to implement his recommendation. Basically what is happening is that when someone logs in correctly it works. When a bad password is entered it does the same redirect and flashes 'successfully logged in' thought they are not. The admin links do not show (which is correct and are the links protected by the <% if admin? %>) but I need it to say 'failed login' and redirect to login path. Here is my code:
SessionsController
class SessionsController < ApplicationController
def create
if
session[:password] = params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
def destroy
reset_session
flash[:notice] = 'Successfully logged out'
redirect_to posts_path
end
end
ApplicationController
class ApplicationController < ActionController::Base
helper_method :admin?
protected
def authorize
unless admin?
flash[:error] = "unauthorized request"
redirect_to posts_path
false
end
end
def admin?
session[:password] == "123456"
end
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
#
end
You need to use Ruby's comparison operator == rather than the assignment operator =. Your create action should be:
def create
if session[:password] == params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
Edit: The problem is that nowhere in your SessionsController are you actually checking the entered password against the correct password. Change your create method to this:
def create
if params[:password] == '123456'
session[:password] = params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "whoops"
redirect_to login_path
end
end
It's not ideal having the password hard-coded like this and storing it in the session for use by the admin? helper method, but this is supposed to be super simple authentication.
if #YOU MISSING SOMETHING HERE WHICH Returns TRUE IF USER IS VALID
session[:password] = session[:password]
flash[:notice] = 'Successfully logged in'
redirect_to posts_path
else
flash[:notice] = "invalid login" #CHange if messaage for invalid login
redirect_to login_path
end
it must be
if session[:password] == params[:password]
You never have a fail condition due to:
if session[:password] = session[:password]
This will always be true. You probably want something like:
if session[:password] == 'canihazpasswrd' then
do_something_here
Edit: Refer #john's answer. :)
Try this:
def create
if session[:password] == '123456'
flash[:notice] = 'Succesfully logged in'
redirect_to home_path
else
flash[:notice] = "Incorrect Password!"
redirect_to login_path
end
end
The thing is that the tutorial you used does no user's authentication. It only checks if the login belongs to an admin, so some content will be showed.
This way you'll never have wrong login/password, just admin/non-admin.

Resources