In my ability.rb file, how can I set it so that only defined users can do things, else (an undefined/not logged in user) cannot do anything?
Example:
def initialize(user)
user ||= User.new #not logged in user
if user.admin_user?
can :manage, :all
else
#can't do anything. Cannot view, edit, or update.
end
end
Thanks!
I've never really used CanCan, but I looked over the docs, and I don't think you need to explicitly define what the user can't do.
You should just be able do something like this in your controller:
if cannot? :destroy, #project
# redirect the user or do something else to disallow access
end
cannot? should return true if the user wasn't assigned a role that has any abilities defined. Conversely can? would return false.
You could try a simple conditional set in your initialize function:
# app/models/ability.rb
def initialize(user)
if user && user.admin_user?
# Abilities for registered admin users
can :manage, :all
elsif user
# Abilities for registered users
can :read, :all
else
# Abilities for no user
end
end
When initialize is called, user will likely (depending on your authentication solution) be nil for not logged in users, which will trigger the last branch.
Related
I'm working on my abilities model on my Rails app to define my user authorization/abilities using cancancan. At the moment, here's what my ability.rb file looks like this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :manage, Application
can :read, User
end
end
end
I'm testing my app now. when I log into an account that doesn't have the admin boolean and go to to say /users, they can access that page, but clicking the show buttons or anything else leads them to the root page and says that they don't have permission. Currently I have an Applications controller/model (poor naming convention, realized later). But I simply wanted to make it so that any user who has a boolean FALSE for if they're admin has different abilities. I want the admin? true person to be able to do anything, but I want everyone else to be only able to SEE THEIR OWN own application (not everything entered by all users), only be able to create one application, and only be able to see their own information on the user show page, and only be able to edit their own user information. Can anyone explain how to specify for the things only the users create and such? Thank you!
define role column into your database and insert following line into your model
generate migration:
class AddRoleToUser < ActiveRecord::Migration
def change
add_column :users, :role, :integer
end
end
insert this into your model like (User.rb)
enum role: [:Admin, :Client, :Enduser, :ClientUser, :Moderator]
then you can manage your permission using cancancan
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can [:new,:create, :update, :destroy], User
end
end
end
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
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.admin == 1 #admin
can :manage, :all
elsif
user.id != nil # registred users
can :read, :all
can :create, Post
cannot :manage, User
else
can :read, :all # guest user (not logged in)
cannot :manage, User
end
Here is my ability file. I want it to make the first registered user the admin and give them all the permissions to edit the whole web page, whilst the User has limited access to only managing Posts and a guest User is only allowed to read posts. However when I use
if can? in my code, the admin is given the same amount of access as a normal user. What am I doing wrong?
In my work I have to do the same thing but with Company.
Every Company creation I check if is the first, if it is, I set it as admin, otherwise, normal user.
The if can? is used here to define if a menu will be hidden or visible. With only that, the user will still access the page if he types the URL so you need to add load_and_authorize_resource so the user gets a message about not having permission.
Is that what you need? =)
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
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