devise update attribute after sign out - ruby-on-rails

I'm trying to update an attribute for the current_user after signing out with devise.
If I use after_sign_out_path_for(resource) the current_user is nil.
When I use Warden::Manager.before_logout works fine just when there is an user signed in.
I have problems with this because I have an API and a client in the same application (client creates, updates, delete, etc through the API)
Is there another way to do it? Maybe a custom action?

Just an idea.
Store the user id in a cookie.
In the after_sign_out_path_for(resource) method, find the user object from this cookie and change the attribute.
def after_sign_out_path_for(resource)
user = User.find(cookies[:user_id])
user.update_attributes(some_attribute: false)
root_path
end

Related

How to use Google Oauth2 for both signing in users and creating new user accounts in a rails app?

I'm working on google authentication for a rails app. Currently using the omniauth-google-oauth2 gem to implement Google auth. I've managed to have users sign in using google. However, I'd also like users to be able to sign up using google. My problem is that I've matched the google callback URL to a particular controller action (sessions#create).
Is it possible to choose between 2 redirect URIs based on whether users are signing in or signing up? Currently, my only idea is to create new google client credentials to be used for sign up, I hope there is a better way.
You don't need to have 2 redirect uris, you just need to do some more work when receiving the callback. For instance:
class SessionsController < ApplicationController
...
def create
email = auth_hash['info']['email'] # assuming your omniauth hash is auth_hash and you're requiring the email scope
#user = User.find_by(email: email) if !email.blank? # assuming your user model is User
if #user
login_user(#user) # use your login method
elsif !email.blank?
#user = User.new(name: auth_hash['info']['name'], email: email)
unless #user.save!(validate: false) # validate false because I'm enforcing passwords on devise - hence I need to allow passwordless register here)
# deal with error on saving
end
else
# deal with no found user and no email
end
end
protected
def auth_hash
request.env['omniauth.auth']
end
end
I've written all steps but the creation process can be shortened to:
#user = User.create_with(name: auth_hash['info']['name']).find_or_initialize_by(email: email)
#user.save! if #user.new_record?
if #user
login_user(#user)
else
# deal with no user
end
Nonetheless, you can't be sure the user is going to give you scope access to the email, so personally I think the first version, even if a bit lengthier is more robust. Then on the shorter version there's also the problem of, if #user is false, why is so? And will require you to add more logic to figure out why is that, whereas in the first one it's much easier to apply the correct response to each situation.

Allow user access to protected page using URL token

I am using Clearance gem for authentication. I have one page in the app to which I want to permit anyone to come provided they have a secure token in the URL / Session. They need not be users in the system.
Is this doable with Clearance. Any hints on how I should proceed. Initially I thought I should override require_login and current_user. Is that a good approach?
Should the secure token page also allow access to people who are signed in, or must everyone have the secure token?
If you must have the secure token, regardless of whether you are signed in with Clearance or not, then I would avoid Clearance for this controller all-together by not calling require_login at all (or calling skip_before_action :require_login if the filter is already in your controller's inheritance tree). Then you could implement your own before_action that checks the token and does whatever you'd like. You could also implement your own current_user for this controller if desired.
If the page should also allow signed in users then I would still skip the Clearance before action and instead use something like this:
def require_login_or_secret_token
unless params["super_secret_security_token"] == TOKEN
require_login
else
end
Then you'd need to override current_user to return a guest object rather than nil if you want to use current_user in this action/view:
def current_user
super || Guest.new
end

Devise sign user out without their session

How can I sign a user out without their session (i.e. they're not the current_user).
I've tried the sign_out(user) controller helper, but that seems to sign out the current_user regardless of the user it's passed.
I can't seem to find a relationship between the sessions table and the users table either.
I'd appreciate any help.
try sign_out #user
where #user is the user instance which admin wants to logout

How do I check if my user is an admin in rails even after new http requests?

My user model has the attributes password, password_confirmation, username, email, and admin.
I'm wondering how exactly do I check whether the currently logged in user is an admin. How would I go about the methods? I've tried if user.admin? on my views, but it seems that doesn't work.
I'm new to rails so any suggestions would be helpful!
There is a "session" hash which persists through the whole session.
Once a user has logged in, you would store the current user's id in the session hash, like so
session[:user_id] = user.id
Now, if you want the current user to be accessible from your controllers and in your views, you can go to apps/controllers/application_controller and make some useful methods...
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user, :signed_in?, :is_admin?
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def signed_in?
!!current_user
end
def is_admin?
signed_in? ? current_user.admin : false
end
end
Now in your views you can use "is_admin?" to check if the current user is an admin, use
"signed_in?" to check if a user is signed in, and "current_user" to access the user object if it exists (if no user is logged in, "current_user" will be nil)
Cheers
I suggest you to consult with this Devise guide. It shows how to create a basic user model with help of Devise and how to perform admin checks. And yes, by giving you this link, I strongly encourage you to use Devise gem for users and all that stuff ;)

Force Restful Authentication to login as a specific user (an admin function)?

I'm using Restful Authentication and I'd like to be able to log in as different users on our site to investigate issues they may be having ("see what they see"). Since all passwords are encrypted I obviously can't just use their passwords.
So, how can I force a session to be logged in as a specific user?
In your sessions_controller add action impersonate like this:
def impersonate
user = User.find(params[:id])
logout_killing_session!
self.current_user = user
flash[:notice] = t(:logged_in)
redirect_to root_url
end
Then in your routes extend session resource with the member impersonate:
map.resource :session, :member => {:impersonate => :post}
Finally, somewhere in your admin views add a button to each user called "Impersonate". It will have to look something like this (assuming that user is in local variable user):
<%= button_to "Impersonate", impersonate_session_path(:id => user.id) %>
Using this approach you also avoid overriding any tracking data such as time of the last login, etc.
P.S. Don't forget to require admin for impersonate action in sessions controller.
Simply override session[:user_id] with the id of the user you want to be. One easy way is to have the user log in as an admin and then give them a drop-down of usernames. When they submit the form, have the controller set session[:user_id] and then reload current_user. The admin will then 'become' that user.

Resources