I'm using STI and have 2 models inheriting from User.
One type of User can only be created by the other user (Admins create Testers).
The problem is, every time I register a new tester with the admin, it creates a session for the tester.
Perhaps there is a documented way to do this somewhere I haven't found? Can I stop devise from automatically starting a session when I register a new user?
Simple solution: DON'T include the :registerable module in the model. I have it in for Admin, out for Tester.
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-after-registration-(sign-up)
This url may help.In Devise we can create custom methods to do after signup.So, in that function you can clear the session and redirect to some other page which you wanted to.
like,
class NewController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
logout_user
flash[:notice[ = "You have to activate before logging in"
redirect_to some_special_page
end
end
Related
I have functionality of inactive account in my application for handling this i override active_for_authentication? method as below
def active_for_authentication?
super && activated?
end
But In my application super admin can also directly login in to other user account, whether it is active or not active
bypass_sign_in(User.find(resource.id))
I used above method for by pass sign in, it allows me to directly sign in only for activated user, when i login for non activated user it goes in infinite loop .
Any solutions to over come this issue or don't run active_for_authentication? callback when bypass_sign_in?
When admin logs in to another user account you can store some additional data in session, that makes it clear that this is the super admin mode.
def login_as(another_user)
return unless current_user.super_admin?
session[:super_admin_mode] = true
bypass_sign_in(another_user)
end
Unfortunately, you can't access session in Rails models, but you can store needed session information in some per-request global variable that is available in models. The solution might be like this:
module SessionInfo
def self.super_user_mode?
!!Thread.current[:super_user_mode]
end
def self.super_user_mode=(value)
Thread.current[:super_user_mode] = value
end
end
In the ApplicationController:
class ApplicationController < ActionController::Base
before_filter :store_session_info
private
def store_session_info
SessionInfo.super_user_mode = session[:super_admin_mode]
end
end
In the model:
def active_for_authentication?
super && (activated? || SessionInfo.super_user_mode?)
end
Also, you should make sure that the :super_admin_mode flag is removed from session when the super user logs out. Maybe it happens automatically, I am not sure. Maybe you will need to do it manually overriding Devise::SessionsController#destroy method (see the example below)
def destroy
session[:super_admin_mode] = nil
super
end
Also read this for better understanding of how devise handles session Stop Devise from clearing session
I recently came across a similar issue where I needed to allow an Admin to sign in as regular Users who were not active in Devise. I came up with the following solution that doesn't involve using Thread.current (which after looking into further online it seems like using Thread.current could be a precarious solution to this problem).
You can create a subclass of User called ProxyUser that has the active_for_authentication? return true. Something like this:
class ProxyUser < User
# If you have a type column on User then uncomment this line below
# as you dont want to expect ProxyUser to have type 'ProxyUser'
#
# self.inheritance_column = :_type_disabled
devise :database_authenticatable
def active_for_authentication?
true
end
end
Then in the controller you want something like this:
proxy_user = ProxyUser.find(params[:user_id])
sign_in :proxy_user, proxy_user
Also in your routes you will need devise to expect ProxyUser so include:
devise_for :proxy_users
And finally when you sign this user out (assuming you can sign the user out in your controller code) make sure to tell devise the scope of the sign out, so you would do
sign_out :proxy_user
And then finally note that in your app you may be expecting current_user in different places (such as if you use CanCanCan for authorization) and now when you sign in as a proxy_user your app will return current_user as nil. Your app will instead have an object called current_proxy_user that will be your signed-in ProxyUser object. There are many ways to handle the issues resulting from your current_user returning nil in this case (including overwriting current_user in your application controller).
I'm trying to implement an e-commerce app. In it, I allow the user to browse for products and put them into the cart even before signing in. I only prompt the user to sign in upon checkout.
However, I'm losing track of the user because the user's session id changes upon sign in. Due to this, Im unable to associate the items that the user placed into the cart (stored in redis) to the user who placed them in after the user signs in to the application.
Does anyone have any idea how could this be circumvented?
Thanks.
Cheers!
Found the solution. All that needs to be done is set session.options[:renew] = false and the session id will still be the same before & after signing in.
Please refer to the implementation below
class SessionsController < Devise::SessionsController
respond_to :json
def create
super
session.options[:renew] = false
end
def destroy
logger.info "Logging out: #{current_user.email}; Session Id: #{session.id}"
$redis.del "cart_#{session.id}"
super
end
end
So I have this app that I'm making where users have profiles after they signup and input their information.
At the moment I'm trying to add a feature that allows for new unregistered users to go to a profile to see what the app is like before they need to sign up (I'm planning on putting a "try it for free" button on the home_controller#index action. For authentication, I'm using the Devise gem.
Currently, I've watched the Railscast (393) on this, but I can't figure out (after several hours of trying) how to implement guest users and log them in using Devise.
I've also read about 4 different solutions on SO, and have decided to stick to this one (how to create a guest user in Rails 3 + Devise):
class ApplicationController < ActionController::Base
def current_user
super || guest_user
end
private
def guest_user
User.find(session[:guest_user_id].nil? ? session[:guest_user_id] = create_guest_user.id : session[:guest_user_id])
end
def create_guest_user
u = User.create(:name => "guest", :email => "guest_#{Time.now.to_i}#{rand(99)}#example.com")
u.save(:validate => false)
u
end
...
end
I have this in my application_controller.rb and don't understand how I would use these functions in the home_controller#index to create a guest user and log into the profile when the "Try it" button is clicked.
I've tried manually creating a user, saving it without authentication and then using Devise's sign_in method on link like so: Try it! and also tried
Try it!
I tried this, but the profile throws some validation messages saying I need to log in to view it. I've also tried removing before_filter authenticate! on the profiles_controller but I can't seem to get this to work at all.
Would anyone know how to create a user on the button click, and auto sign them into a guest profile? Thanks a lot for any help, I'm completely lost here.
I think you have a misunderstanding on what a guest user is. You say that you want guest users to auto sign in, and that is wrong. Guest users can't sign in, because... Well, because they are guests. You want to create them, but not sign them in.
This is why you want these helper methods in your ApplicationController, because when you try to get the current_user, if that doesn't exist (nil), you will have a fallback (that is why you use the || operator), that will assign a guest_user as a current_user.
So, forget about using sign_in links for guest users and you should be fine.
If I've got a rails application and I'd like to add authentication to with Devise, how would I allow users who have a null password in the database to sign in without one?
I'm interested in hearing answers along the lines of the lifecycle and what files I'd have to author to get it done.
Step 1: Allow the record to be saved.
Step 2: Sign in the record
To allow the record to be saved, you'll want to do validations yourself. I describe here how to do custom validations: http://jessewolgamott.com/blog/2011/12/08/the-one-where-devise-validations-are-customized/ .... In your case, you'll want to remove the password validations.
To sign in the record, you'll need to have a custom sign in path. You can override the devise sessions controller, but this could do the trick:
class SessionsController < ApplicationController
def create
user = User.find_by_email!(params[:session][:email])
sign_in user
redirect_to root_path
end
end
It turns out, Devise is built on Warden. This means that I only have to create my own custom Warden strategy:
https://github.com/hassox/warden/wiki/Strategies
I am using Devise for authentication in my application.
How do I forbid certain users from signing in - kind of disable a user?
Do it like this:
Create a column called is_active for the User model.
Then add the code below to the User model:
class User < ActiveRecord::Base
#this method is called by devise to check for "active" state of the model
def active_for_authentication?
#remember to call the super
#then put our own check to determine "active" state using
#our own "is_active" column
super and self.is_active?
end
end
UPDATE
As Matt Huggins notes, the method is now called active_for_authentication? (Documentation)
Add a column to the User model: allowed_to_log_in.
Then add this to /app/models/user.rb:
def active_for_authentication?
super and self.allowed_to_log_in?
end
If you want to inform the user with a custom message you can add this as well:
def inactive_message
"You are not allowed to log in."
end
I think that is quite important because the standard message from Devise says:
"Your account is not activated yet."
That is confusing for users and the real reason is that you have "banned" them from logging in.
You want to do authorization, not authentication. Devise only does authetication, though.
I.e. devise only tells you that a user is who he says he is.
You need something else to forbid him from using the site.
Authorization is a popular topic and there's a whole list of gems that can help you with it:
http://ruby-toolbox.com/categories/rails_authorization.html
Take your pick.
Sounds like you may be interested in cancan
https://github.com/ryanb/cancan
http://railscasts.com/episodes/192-authorization-with-cancan