Devise role based routing - ruby-on-rails

I have an app with multiple users. Each user as a theoretical role (user, client, etc). I've designed a view/controller for each user type.
I want to be able to login each type of user do a different root url and lock them to it.
Originally I was going to add a column to Users in Devise called role and so I can differentiate the users. The problem I'm having is how to say in routes.rb if current_user.role == "client" root :to => 'controller#index'
Once they are logged in to the page I also want to keep them from being able to visit any of my other paths ie: domain.com/calls domain.com/units
I've been looking into cancan to run alongside Devise but I'm not sure if this is the answer.

Instead of handling it in routes, why not handle it in ApplicationController?
#application_controller.rb
before_filter :direct_to
def direct_to
if current_user.role == "client"
redirect_to client_controller_path
# etc
end

Related

Defining Admins Rails

How can I define a method between Users and Admins? I am using Omniauth Twitter for my users but there are actions that I want to make sure users can not do if they are not admins. I have bundled the gem Active admin but because I am not using devise, any user can currently access the Admin dashboard.
If it were me, I'd create a role attribute on your User model, and have it default to say "customer" or whatever a default user is, but have the ability to set some user's role to "admin". You should be able to set that using Active Admin's edit page. Than create a custom method on your User model, or maybe create a helper method, whatever you prefer...something like:
def admin?
if self.role == "admin"
true
else
false
end
That way you wrap sensitive info (like info on your dashboard) in a user.admin? if statement.
if user.admin?
..display stuff..
end
Or check out this: http://activeadmin.info/docs/13-authorization-adapter.html

How do I create the users root path route using the Devise gem?

I did a search and found this question on SO, but the accepted answer doesn't seem to be working for me. Basically, the Divise wiki says...
After signing in a user, confirming the account or updating the
password, Devise will look for a scoped root path to redirect. For
instance, for a :user resource, the user_root_path will be used if it
exists, otherwise the default root_path will be used.
With my amateur knowledge of RoR, I have a devise model called Player, and I created the following statement in my routes.rb file...
match 'player_root', to: 'pages#play', as: :player_root, via: :all
...but with that, my app always redirects to my root path, instead of the players root path, which I defined above. What am I doing wrong?
Thanks in advance for your wisdom! Also, I'm using Ruby 2 with Rails 4.
As I understand, you are trying to specify root_path for :players.
If order to do that, you can use following:
authenticated :players do
root to: 'pages#play', as: :authenticated_root
end
This will give you custom root_path for signed in users (players).
Further to Andrey Dieneko, there are two other options you have:
Use unauthenticated_path
Use authenticate_user! in your controller
The bottom line here is that you may be thinking about incorrectly. You may be trying to work out where to take users if authenticated. However, you may be better suited to actually using the authentication methods in the controller to test whether the user is logged in, and if not route them to a login page:
#config/routes.rb
root to: "players#play"
#app/controllers/players_controller.rb
class PlayersController < ApplicationController
before_action :authenticate_user!
end
This will take a user to the "login" path if they are not logged in.
Alternatively, you can use unauthenticated_path like so:
#config/routes.rb
root to: "players#play"
unauthenticated do
root to: "application#landing"
end
--
This method will only be best if you have an app like Facebook (IE it has no "landing page" etc)
I think Andrey's answer is more apt (especially if you have a landing page)

Rails How to Login a Guest User with Devise

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.

Determine redirect paths after sign up with Devise

I can have two types of users sign up on my app, "girls" and "boys". If a girl signs up I want to redirect to "/girls" and if a boy signs up I want to redirect to "/boys".
Is it possible to do custom redirection with Devise?
The closest docs I found are here: https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in. The problem is I can't do any check to switch the redirect route.
Options I've considered:
Pass an additional URL param when user clicks "sign-up". like
?is_girl=1.
After they click sign-up, when determining the redirect route, I could look at the users model and see if they're a girl or boy. Then redirect accordingly.
I am going to assume as part of the sign up process you ask them if they are a boy or girl and this is saved in the database.
So you would just need to do like the example in the Devise docs is showing
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
if resource.sex == 'boy'
'/boy' # or you could create a route in routes.rb and do boy_path
else
'/girl' # with routes setup: girl_path
end
end

how can we use cancan gem without being log-in?

I am trying to make a cancan permissions for visitor who doesn't have to login to get some services. To clarify this for example:-
I've a search controller which has new and search actions . In the related new viewer there's some links, some of them I don't want to be seen for non-login users and others must be seen for them!..
I've tried to write these lines in the controller search :-
before_filter :authenticate_user! # this forces the user to log-in ( I don't want this )
load_and_authorize_resource # this doesn't work without authenticate_user
before_filter :load_permissions
in the new view I wrote this
<%= link_to "Listing Managment", extras_path if can? :index, Role %>
but it raises an error for me because of ( can? )
hint: the error arises when I remove the controller's 3 before filter
above. But still not convenient when I put them.
In your cancan initializer you can use something like
user = current_user || User.new
That way cancan will pick up the current user (who may have roles) and if there is no current_user (you are not logged in) will return a dummy user record (anonymous user) with no active roles.

Resources