I'm running a Rails 3.2.14 app with Devise 2.1.2 and am checking for concurrent/duplicate sessions in my application controller.
I'd like to be able to display a flash notice in template view after I call signout_and_redirect in my application controller that displays "Duplicate login detected"
Here's what my code looks like:
application_controller.rb
def check_concurrent_session
if duplicate_session?
flash[:notice] = "Duplicate Login Detected"
sign_out_and_redirect(current_user)
end
end
def duplicate_session?
user_signed_in? && (current_user.login_token != session[:token])
end
I've tried it with the above code, but when I trigger a duplicate session the browser does sign out but does not display the flash notice.
In my application.html.erb I have the following setup to display flash notice/alerts.
<% if flash[:notice] %>
<p class="alert"><%= flash[:notice] %></p>
<% end %>
<% if flash[:alert] %>
<p class="alert"><%= flash[:alert] %></p>
<% end %>
Could you use session?
def check_concurrent_session
if duplicate_session?
sign_out_and_redirect(current_user)
session[:duplication_notice] = "Duplicate Login Detected"
end
end
# users/sessions_controller.rb
def new
if session[:duplication_notice].present?
flash.now[:alert] = session[:duplication_notice]
session.delete(:duplication_notice)
end
super
end
Lifetime of flash is until next action.
sign_out_and_redirect
authenticate_user!
sign_in
log
Started GET "/" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::FunctionsController#home as HTML
Filter chain halted as :check_concurrent_session rendered or redirected
Completed 302 Found in 9ms (ActiveRecord: 0.9ms)
Started GET "/" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::FunctionsController#home as HTML
Completed 401 Unauthorized in 1ms
Started GET "/users/sign_in" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::SessionsController#new as HTML
Completed 200 OK in 3258ms (Views: 3254.7ms | ActiveRecord: 0.3ms)
Because sign_out clear the session, session set after sign_out.
Anything you place in the flash will be exposed to the very next action
You can sign out without redirecting and make the redirect with flash message later. Using the after_sign_out_path_for method will ensure that you use the correct path for redirect even if it has been customized.
Following your example:
if duplicate_session?
user = current_user
sign_out(user)
redirect_to after_sign_out_path_for(user),
alert: 'Duplicate Login Detected'
end
For the more recent version of devise, you could also redirect to a new user session path after clearing the user session.
if duplicate_session?
flash[:notice] = "Duplicate Login Detected"
sign_out current_user
redirect_to new_user_session_path
end
This will persist the flash after redirect
Related
Having some issues parsing and retrieving a put request from a raspberry pi I have sending my website data.
I am trying to update some fields in my Worker model the controller is below
class WorkersController < ApplicationController
def new
#worker = Worker.new
#user = User.find(params[:user_id])
end
def create
#user = User.find(params[:user_id])
#worker= Worker.new(params[:worker])
#worker.user_id= #user.id
if #worker.save
flash[:success] = "Worker information saved!"
redirect_to #user
else
render 'new'
end
end
def show
end
def update
#user = User.find(params[:user_id])
#worker = Worker.find(params[:id])
#MHS = params[:SUMMARY][:MHS_av]
#worker.hashrate = #MHS
#worker.save
end
end
Below is the server side incoming put request
Started PUT "/users/1/workers/1" for xxx.xxx.xx.xxx at 2013-06-13 03:06:02 +0000
Processing by WorkersController#update as XML
Now here are the parameters
Parameters: {"STATUS"=>[{"STATUS"=>"S", "When"=>1371092750, "Code"=>11, "Msg"=>"Summary", "Description"=>"cgminer 3.1.1"}], "SUMMARY"=>[{"Elapsed"=>60394, "MHS av"=>1.92, "Found Blocks"=>1, "Getworks"=>1217, "Accepted"=>9104, "Rejected"=>138, "Hardware Errors"=>0, "Utility"=>9.04, "Discarded"=>2428, "Stale"=>20, "Get Failures"=>1, "Local Work"=>9513, "Remote Failures"=>0, "Network Blocks"=>458, "Total MH"=>116212.6295, "Work Utility"=>1769.84, "Difficulty Accepted"=>1747840.0, "Difficulty Rejected"=>26496.0, "Difficulty Stale"=>3840.0, "Best Share"=>74960510}], "id"=>"1", "user_id"=>"1", "worker"=>{}}
Followed by these Errors
WARNING: Can't verify CSRF token authenticity
at=info method=PUT path=/users/1/workers/1 host=miningmonitor.herokuapp.com fwd="xxx.xxx.xx.xxx" dyno=web.1 connect=1ms service=1029ms status=500 bytes=643
TypeError (can't convert Symbol into Integer):
app/controllers/workers_controller.rb:27:in `[]'
Completed 500 Internal Server Error in 345ms
app/controllers/workers_controller.rb:27:in `update'
I See that Ruby on rails is thinking the incoming message is XML but its JSON do I need to specify somewhere that this put request is JSON? Also I was told Ruby on rails just parses JSON into the params and I can just pull the data from the params is that true?
adding content from application.html.erb from layouts
<head>
<title>Mining Monitoring Website</title>
<%= stylesheet_link_tag "application", media: "all"%>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
Look at it closely - SUMMARY is an array, not hash. I don't know how you're building POST (PUT) data, but accessing them in following way following should work
params[:SUMMARY][0][:MHS_av]
Also - please take a look at MHS_av - it looks like in incomming parameters it does not have an underscore.
CSRF is mising by a reason, right?
I have a link to logout.
<a href="http://mydomain.lvh.me:3000/users/sign_out" data-method="delete" rel="nofollow">
Sign Out
</a>
Which correctly executes the sign out action:
Started DELETE "/users/sign_out" for 127.0.0.1 at 2013-02-08 15:04:06 -0200
Processing by DeviseCustom::SessionsController#destroy as HTML
Parameters: {"authenticity_token"=>"WYMm9e4VMNgdDFXbl59TKyylhX+rZlWbWMF8lVEeves="}
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 150 LIMIT 1
(0.1ms) BEGIN
(0.2ms) COMMIT
Redirected to http://mydomain.lvh.me:3000/
Completed 302 Found in 4ms (ActiveRecord: 0.5ms)
I am customizing SessionsController but I am not redefining the destroy action.
class DeviseCustom::SessionsController < Devise::SessionsController
respond_to :html, :js
layout :false
def create
<MYCUSTOMCONTENT>
end
end
But after doing all this, current_user still holds the information of the logged user.
Any help?
Ensure that you've included the default javascript files in your layout. There should be a line like:
<%= javascript_include_tag :defaults %>
in your layout.
need a logout via GET then add this to your
config/initializers/devise.rb:
config.sign_out_via = :get
I am using devise and create login with Facebook using omniauth, but having problem of lost the devise helper methods access like current_user and user_signed_in? methods are not working.
EDIT
AuthenticationController
def create
omniauth = request.env["omniauth.auth"]
user = User.find_by_provider_and_uid(omniauth["provider"], omniauth["uid"]) || User.create_with_omniauth(omniauth)
session[:user_id] = user.id
redirect_to dashboard_path(user.id), :notice => "Signed in!"
end
redirect_to USercontroller dashboard method
UserController
before_filter :logged_in
def dashboard
#user = User.find(params[:id])
#comment = Comment.new
#comments = #user.comments.all.paginate(:page => params[:page], :per_page => 5)
end
so here control should go to dashboard method after checking logged_in method in ApplicationController
logged_in method in ApplicationController
Application Controller
def logged_in
if user_signed_in?
return true
else
redirect_to root_path
flash[:message] = "please login"
end
end
when I logged in using facebook following code generated at console
Started GET "/users/52/dashboard" for 127.0.0.1 at Thu Mar 29 12:51:55 +0530 2012
Processing by UsersController#dashboard as HTML
Parameters: {"id"=>"52"}
Redirected to http://localhost:3000/
Filter chain halted as :logged_in rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.0ms)
in the above code control is render from logged_in method to root_path but it shold render dashboard_path
So I am guessing User_signed_in? helper is not working I also use current_user in stead of that generate same error
As I see, user_signed_in? is working, but returns false, as for Devise user is not logged in. To fix this, just replace the session id storing with Devise sign_in method in your controller action:
def create
omniauth = request.env["omniauth.auth"]
user = User.find_by_provider_and_uid(omniauth["provider"], omniauth["uid"]) || User.create_with_omniauth(omniauth)
sign_in(:user, user)
# actually if you really really need that id in the session, you can leave this line too :)
session[:user_id] = user.id
redirect_to dashboard_path(user.id), :notice => "Signed in!"
end
After creating the user account via Facebook, how do you sign in the user?
You should still be using devise helpers like sign_in_and_redirect. Something like:
user = User.build_from_omniauth(omniauth)
if user.save
sign_in_and_redirect(:user, user)
end
Then you should be able to use helpers like current_user and user_signed_in? (which just check if current_user is not nil).
Taking a look at your edit, my answer is still valid. What you need to do is use sign_in_and_redirect(:user, user) instead of just setting the id in the session.
You can easily customize where the user is redirected after sign in with devise.
Another thing, remove this logged_in filter, Devise has a authenticate_user! method that you can use as a before_filter. It will redirect the user to the sign in page, and when they login, it will redirect them to the page they were trying to access.
You're using Devise, so try to take advantage of that, and go read the doc ;)
I am a newbie in Rails. I try to build a simple authenticate system, to application_controller I put following lines:
def check_session
if session[:user]
if session[:expiry_time] < 10.minutes.ago
reset_session
flash[:warning] = 'You was logout.'
redirect_to root_url
else
session[:expiry_time] = Time.now
end
else
#... authenticate
session[:expiry_time] = Time.now
flash[:warning] = 'You was logout.'
redirect_to root_url
end
end
My problem is in one action - in this action I check, if the user is log in or not. And if the user is log in, so I will render one template, and if not, so I will render the second one. It looks like:
<% unless session[:user].nil? %>
<%= render :template => 'template_for_login_user' %>
<% else %>
<%= render :template => 'template_for_not_login_user' %>
<% end %>
And here is the problem - this doesn't works me. At least... well - if I am not log in, so will be render the template template_for_not_login_user and if I am, so template_for_login_user. This is right.
But if I am log in and I am on the template_for_login_user, but I am 15min idle => the session will be expired => I should be redirect to login form. But here is the problem - I am 15 minutes idle and I refresh this page, so I am still on the action template_for_login_user - and this is the problem...
I would like to ask you - can you help me please, where could be a problem? What I'm doing wrong?
In your ApplicationController, did you add a line like this :
before_filter :check_session
if some controller action don't need the user to be authenticated, you can add this:
skip_before_filter :check_session, :only=> [:index, :search, etc..]
in this example, this would skip your before_filter :check_session on action : index and search. This way you have a global behavior that always check the session for a user logged on. But you can skip this in particular controller where some actions don't need the user to be authenticated
I'm trying to do a redirect while setting the flash[:error] value. (Rails 3.0.10)
In my view I have
<p id="error"><%= flash[:error] %></p>
<p id="notice"><%= flash[:notice] %></p>
If I do a redirect_to show_path, :notice => "ok" it works fine, but if I do redirect_to show_path, :error => "error" it doesn't show up.
what could I be missing?
As stated in the Rails API only :notice and :alert are by default applied as a flash hash value. If you need to set the :error value, you can do it like this:
redirect_to show_path, flash: { error: "Insufficient rights!" }
If you are having problem to keep the flash after redirecting to another path, then use this.
flash.keep
in your method, before redirecting.
To truly follow the PRG pattern, I wonder if this project works well
https://github.com/tommeier/rails-prg
I can't stand apps not following PRG as a user.....I have been 6 pages after a POST and hit the back button to get back to 10 pages ago get blocked by "do you want to repost this crap"....no, of course not. I just want to get back to a page I had seen before.
non-PRG apps are very very annoying to users.
controller.rb
flash[:sucess] = "Your sucess message"
redirect_to action: :index
layout.html
<% if flash[:sucess] %>
<div class="alert alert-solid-success alert-bold" role="alert">
<div class="alert-text"><%= sanitize(flash[:sucess]) %></div>
</div>
<% end %>