How to make current_user always be not nil in Rails application? - ruby-on-rails

Please, give me any idea about a little problem: in my Rails 3 app I need current_user always be NOT nil. I'm using Devise and CanCan for auth system and I thinking about how to implement "guest" user. For roles like "admin" it works fine ( if current_user.is? :admin), but if user is not logged in I wish to check not user_signed_in?, but the same way (if current_user.is? :guest) for example.
I think I need to put somthing creating current_user object ib before_filters of Application_Controller, but I dont' know how to create this global thing right way.
Thanks for any answers!

You could try it like this:
if current_user.try(:is?, :admin)
So it won't matter if current_user is nil

If you are using 'CanCan' you should be adding functionality like you mentioned into you Abilities class. For example:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
can :manage, :all if user.is? :admin
can :read, :all if user.is? :guest
end
end
For more information take a look through the Wiki or watch the screen cast:
https://github.com/ryanb/cancan/wiki
http://railscasts.com/episodes/192-authorization-with-cancan

Related

CanCan Abilities Definition

In my rails application, my user is able to login once and switch between accounts as they please. When they do, I need to reinitialize their abilities since the permissions are set at the account level in the database.
My initial thought is to initialize the ability class when I detect a change in the account but not sure how to accomplish this.
I am of course open to any other idea. I am new to CanCan.
The Ability class is where all user permissions are defined.
Example:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
The 'can' method is used to define permissions and requires two arguments. The first one is the action you're setting the permission for, the second one is the class of object you're setting it on.

Understanding CanCan Ability and Users

I have Rails Admin with CanCan support in my rails app. I'm confused on one issue though. How does CanCan know what user is signed in? For example, my users can have different roles and through CanCan I assign roles for certain access into each table. When I go to localhost:3000/admin, I receive the error
CanCan::AccessDenied in RailsAdmin::MainController#dashboard
My Ability.rb file
def initialize(user)
if user and user.role.eql? :super_admin
can :manage, :all # allow superadmins to do anything
elsif user and user.role.eql? :admin
can :manage, [Location, School] # allow admins to manage only Locations and Schools
end
end
So what do I do so that user's have the ability to sign in into Rails Admin? Do I have to manually create it?
By default, CanCan will use whatever is returned by current_user. If you are using Devise within a namespace though (admin for example) then Devise actually will use current_admin_user instead. You can either create a current_user method in your ApplicationController (or some other base controller) that returns current_admin_user or overwrite the current_ability method to instantiate the Ability with current_admin_user instead.
(this is all assuming your Devise is using a namespace. By default Devise will use current_user)
You need to have a current_user method available in your controller. Assuming you have that, if you aren't signed you won't have access to a current user, so you'll need to assign a user in your ability file if it doesn't exist. In your initialize method, add user ||= User.new to make the assignment if a user doesn't already exist.
def initialize(user)
user ||= User.new
if user and user.role.eql? :super_admin
can :manage, :all # allow superadmins to do anything
elsif user and user.role.eql? :admin
can :manage, [Location, School] # allow admins to manage only Locations and Schools
end
end

Security: using CanCan to make sure user cannot see other users' profiles

I've got an app that uses Devise, CanCan and Rolify to deal with authentication and authorization. But I don't think I'm using these gems to the full extent. Right now the only thing in my ability class is this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.has_role? :admin
can :manage, :all
else
can :read, :all
end
end
end
I found a security hole where an authenticated user is able to look at other user profiles. I fixed it by changing some code in the user controller.
def show
#user = current_user.has_role?(:admin) ? User.find(params[:id]) : current_user
end
Is this the best way to deal with this hole? Is there a best practice or a rails convention that addresses this in a different way?
From the doc:
can :read, ModelName, :user_id => user.id

cancan gem simple question

models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.role? :admin
can :manage, :all
else
can :read, :all
can :create, Comment
can :update, Comment do |comment|
comment.try(:user) == user || user.role?(:moderator)
end
if user.role?(:author)
can :create, Article
can :update, Article do |article|
article.try(:user) == user
end
end
end
end
end
In Railscasts there are methods user.role? :admin & if user.role?(:author).I dont get it. Do i need to create a method in model to make it work?
I'm storing roles in Users table as a role column.
Yes, you need to write this yourself. However, the CanCan project has a wiki page describing how to do this.
The first line of the wiki says:
"CanCan is decoupled from how you
implement roles in the User model, but
how might one set up basic role-based
authorization?"
Note that I disagree almost completely with the example on that page that uses a role_mask, but the page is still good and should give you some ideas.
There is also the Separate Role Model example, which I personally like better. It depends on where you want to store your role information.
If you're looking for a gem that is plug-and-play, then check out Declarative Authorization.
Raynb says that he developed Cancan because DA was overkill for some projects here: http://railscasts.com/episodes/192-authorization-with-cancan?autoplay=true

Nil in CanCan initialize parameter in ability.rb model

I'm following the tutorial from Ryan B, but I got something wrong when trying to inspect the user's role.
Why I got a nil initialize parameter when I inspect it. Are there any connection between the initialize parameter with the Person Object, in Ryan's tutorial is using 'user' parameter on initialize method and User Model. Am I forgetting something basic here? These are my codes, Thanks!
class Ability
include CanCan::Ability
def initialize(person)
raise person.inspect
can :read, :all
end
end
Most likely there is no logged in user when you are running this code. You need to create some sort of guest user to check permissions against non logged in users
def initialize(person)
user ||= User.new
if user.role? :somerole
can :read, :all
else
#whatever guest can do
end
end

Resources