Current_user nil after creating a session in ROR with AuthLogic - ruby-on-rails

I'm having a bit of problems with AuthLogic and current_user.
I have a Flex4 application using the Cairngorm framework as the front-end, and Ruby On Rails as the back-end.
I can log in fine through a browser, and when only using ROR. However, when I try it through my Flex4 application, it will fail the first time but work the second time.
What is happening, is inside the user_sessions_controller.rb I have a call to
self.current_user.to_xml;
The first time I call the create action, the current_user object returns nil. The second time I call it (without restarting the server, or browser) it will be the proper current user.
So this leads me to believe that the current_user is being set sometime after the render command inside my create action.
If I need my rails controller to return the current user in the create action, how would I go about doing that?

Was just having the exact same problem...not sure why this happens but I was trying to call current_user in my create method in my user_sessions_controller.rb, solved as per below...
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
current_user = UserSession.find.user
current_user.increment_login_count_for_current_memberships!
flash[:notice] = 'Sign in successful.'
redirect_to root_path
else
render action: "new"
end
end
Hope this helps!

This is because the helper methods current_user is typically defined as a before_action. What means, the before action did not run before you use it during the session create.
I also used this UserSession.find.user which is perfectly fine for this usecase.
Cheers,
Niklas

Related

updating sign_out time into database upon user sign out

Am trying to update my database with signout time upon user sign out of the application but my solution does not work.
Here is what I have done below:
So I defined a method which I call in destroy action to update my database with signout time but it doesnt work, rather it throws argument error.
update_method
# the `save_signout_time` is what I have done to update logout_time upon sign out.
def save_signout_time(member_id)
SigninHistory.update(
logout_time: Time.now
)
end
def destroy
save_signout_time current_user.id
clear_all_sessions current_user.id
reset_session
redirect_to root_path
end
What am I missing? Or how do I go about this?
Your function save_signout_time takes a member_id but then you don't use that member_id for the update.
If you want to update a single record the way you have it architected right now, you need to:
SigninHistory.update(member_id, logout_time: Time.now)

Can I override just part of an ActiveAdmin controller action using `super` + custom redirect?

I've registered a Widget in ActiveAdmin and want to change the redirect that takes place after creating a new one. So that I can accomplish various things with Javascript, I've created a custom form for creating/editing them such that in /admin/widget.rb I have this:
form do |f|
render "create_or_edit_widget"
end
I want to modify the basic Admin::WidgetsController#create action to change where the user is redirected after successfully creating one. I can fill out the rest of the custom action to complete this, except I don't know how to handle a case where the .save fails and the user is redirected back to the form with the formtastic inline error messages. I know how I could do this if I wanted the normal Rails form behavior of creating a list of error messages but not enough about Formtastic to copy its behavior. So far I have this:
controller do
def create
#widget = Widget.new(params[:widget])
if #widget.save
redirect_to admin_widgets_path, notice: "Successfully created Widget."
else
redirect_to :back
end
end
end
I was wondering if I can somehow user super and then only change the redirect path after successful creation instead of having to write out the entire action. If that's not possible, can anyone tell me where in the ActiveAdmin GitHub I'd be able to find the standard #create action so I can copy it out and change the one part?
Yes, you can do that. Here is a working code from my application using super and just changing the redirection
def create
super do |format|
redirect_to admin_submission_discussion_path(id: resource.discussion.slug, submission_id: resource.discussion.client_application.slug) and return if resource.valid?
end
end

when to render with instance variable, and when to redirect?

My new and edit pages depend on an #important_data instance variable that is not used in the create and update actions.
As a result my page can't render the new page upon failure.
def create
#my_object = MyObject.new(params[:my_object])
if #my_object.save
redirect_to root_path
else
render action: "new"
#this can't render because the page asks for an #important_data variable that's not defined.
end
end
Which of the two solutions below should I choose?
What are the advantages/disadvantages of each?
OPTION 1: declare #important_data prior to render
def create
#my_object = MyObject.new(params[:my_object])
if #my_object.save
redirect_to root_path
else
#important_data = ImportantData.all
render action: "new"
end
end
OPTION 2: Redirect
def create
#my_object = MyObject.new(params[:my_object])
if #my_object.save
redirect_to root_path
else
redirect_to new_my_object_path
end
end
When you use render, you're using #my_object with the attributes updated from params[:my_object]. Most of the case, this is what you want. When you show the page to the user, you want to preserve the changes they made to the form and show them the errors.
When you use redirect, you're doing a different and additional request so the parameters submitted from the form are not preserved (unless you pass them in your call to redirect and build them up in the controller action).
So in most cases, you'll definitely want to declare #important_data when the validation fails. I can't think of a case where you'd want to redirect.
Offcourse, the Option1 will work best, since you are rendering new in case of errors only. Also, redirection li'l bit mess up the user experience, it will take a bit long to render the page again with same query #important_data = .... running again.
I think you should use OPTION1
So the place where redirect_to should be used is when you're doing a HTTP POST request and you don't want the user to resubmit the request when it's done (which may cause duplicate items and other problems).
In Rails, when a model fails to be saved, render is used to redisplay the form with the same entries that was filled previously. This is simpler because if you use redirect, you'll have to pass the form entries either using parameters or session. The side effect is that if you refresh the browser, it will try to resubmit the previous form entries. This is acceptable because because it will probably fail the same way, or if it's successful now, it was what the user should expect in the first place anyway.
The above answer is referenced from: Are redirect_to and render exchangeable?

Rails 3 with Authlogic and calling reset_session

The RoR Security Guide states that you should "issue a new session identifier and declare the old one invalid after a successful login" using the reset_session method to counter session fixation.
I haven't been able to find any guidance on calling reset_session when using Authlogic. Is it simply a case of including the method in the controller method (as below)?
I'm just concerned about causing problems for Authlogic as I can see both user_credentials and user_credentials_id keys and values in the session hash prior to calling reset_session.
class UserSessionsController < ApplicationController
def create
#user_session = current_client.user_sessions.new(params[:user_session])
if #user_session.save
reset_session
flash[:success] = I18n.t(:msg_login_success)
redirect_back_or_default application_root_path
else
render :action => :new
end
end
For reference this is my current method:
def create
#user_session = current_client.user_sessions.new(params[:user_session])
if #user_session.save
# reset session to counter session fixation
# whilst retaining values except for those that the application has created specific to the current user
temp_session = session.merge("current_user" => {}).clone
reset_session
session.reverse_merge!(temp_session)
# set flash msg and redirect
flash[:success] = I18n.t(:msg_login_success)
redirect_back_or_default application_root_path
else
render :action => :new
end
end
With the call to reset_session still performed after a successful login as per the recommendation in http://guides.rubyonrails.org/security.html#session-fixation-countermeasures
yeah, resetting the session AFTER you log the user in (which is what looks like happening?) is definitely not right. You want to do it BEFORE you log the user in.
Ideally you'd want to do it before you log the user in but only if the login is actually going to be succesful -- but I'm not sure if you can get auth_logic to do that, I'm not very experienced with auth_logic, although it's a REALLY good question for auth_logic, if I were you I'd file it as a support ticket with auth_logic.
But in the meantime, you might want to just try putting the reset_session at the top of the action method, before #user_session = current_client.user_sessions.new(params[:user_session]). I think this will work, and at worse reset the session in some cases where you really didn't have to (if the user's credentials were invalid), but I don't think that will cause a serious problem. (uh-oh, unless it causes you to lose your validation errors?)
But again, not an auth_logic expert here. I don't expect you to accept this answer since I don't have the expertise to really answer it, just sharing what I think in case it helps you and gives you some pointers as to how to think about it.

Rationale behind render :new instead of redirect_to new for POST create?

Given a rails RESTful controller
class WidgetsController
def new
#widget = Widget.new
end
def create
#widget = Widget.new(params[:widget])
render :new and return unless w.save
redirect_to widget_path(#widget)
end
end
Other than to capture the parameters and render validation messages why is the convention to render :new instead of redirect_to new_widget_path if validation fails?
As URL will alter from /widgets/new to /widgets if validation fails doesn't this break the concept of REST?
Render will not call the controller action, so the instance variables that you have set in the create action will be taken to the new view.
this means that any validation errors persist in the new view...
redirect_to would run the controller action for new, and therefore create a new instance of your model... and you would loose the errors...
hope this helps
Could you do this instead of rendering the new action?
flash[:thing] = params[:thing]
redirect_to new_thing_path
Then in new
#thing = Thing.new(flash[:thing] || params[:thing])
This honestly seems nicer to me because otherwise if you have any logic in your controller that is required to render the new/edit actions, you have to repeat that logic (or create some before_filter or something) in update/create. I realize this involves one more request but aside from that it seems simple and safer to code (apart from the fact that you are breaking rails conventions) and it gives the user a valid url that is always the same for looking at/doing the same thing.
If they refresh they'll lose their values but that is true of any form before being submitted. And that seems to make more sense to me than refreshing resulting in a resubmit warning which is pretty strange. How is a user supposed to clear the form for example?
This rails-ism has always bugged me. Are there are any serious issues with this that I'm not considering? Do other application frameworks all do the same?
The thing with render is that it will not cause another request to be generated. It will go to the corresponding view and display it. With redirect, however, a redirect request to the browser will be generated, which will cause another request to your server.

Resources