Rails Permissions: CanCanCan Abilities- Show only what user creates - ruby-on-rails

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

Related

RailsAdmin + Devise + CanCanCan role not works without :manage :all

I apologize in advance for my English and knowledge of ruby :)
I making admin panel with RailsAdmin, authentication with Devise, authorisation with CanCanCan, so, I have three boolean fields in User:
add_column :users, :superadmin_role, :boolean, default: false
enter code hereadd_column :users, :manager_role, :boolean, default:
So, in ability.rb i have this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :access, :dashboard # allow access to dashboard
can :access, :rails_admin # access Rails Admin for Admin-users
if user.superadmin_role?
can :manage, :all
end # role works correct
if user.manager_role?
can :read, :all
end #role works incorrect
end
end
SUPERADMIN_ROLE works correct and allow to enter to RailsAdmin and etc., but MANAGER_ROLE is doesn't work - when user try enter in Dashboard, there is an Access Denied error message is showing:
How to provide access for manager_role to dashboard and RailsAdmin interface - have broke the whole brain.
I will be glad to any help (ready code, links #where to read and etc) and constructive criticism
cancancan2 needs a different adapter for RailsAdmin. Please look at this issue: https://github.com/CanCanCommunity/cancancan/issues/413 and this issue: https://github.com/sferik/rails_admin/issues/2901.
On the first link you will find the code needed to create an adapter.

How can i allow user with admin role to edit the role of the other users?

I use devise for authentication and only an admin can create a user.
I use cancan to assign roles to the user during user creation.
I want the admin to view all the users roles and the admin should be able to edit the roles of the users.
How can I do this?
Check out https://github.com/marklocklear/devise_multi_tentant. In ability.rb I have...
class Ability
include CanCan::Ability
def initialize(user)
can :manage, :all if user.role == "admin"
end
end
You can add a role attributes for User model.
Then, when user go to admin dashboard, you can check user's role. If user isn't admin, redirect to another page (using before_filter :function)
But, instead doing everything manually, you can use gem cancan instead, it's so popular and easy to use!
You can find the document here: GitHub
Or in rails cast episodes 192
Basically, it'll create a ability model, and you will declare privilege for user, a sample ability class
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :update, User
end
end
end
After that, you can authorize for user in action, controller or views, like the example see this link
PS: sorry if my English was too bad, thanks:)

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

Using CanCan to limit view on index page to user_id

I am utilizing Devise and Cancan for a rails 3.2.6 application. In the application, I allow users to create a document with some information gathered in a form. I then want to allow the user to list on a Document index page at localhost:3000/users/1/documents only their documents, which this is working. What isn't working, is I am trying to limit the user from being able to see everyone else's documents by replacing the /users/:id/documents with another number.
I am using cancan and have tried both
can :index, Document, :user_id => user.id
can :read, Document, :user_id => user.id
and then on the Document controller index method
if can? :read, Document
#documents = #user.documents
else
redirect_to root_path
end
also tried with :index as well...but this isn't working. I am also using load_and_authorize_resource..
Any thoughts on what I am missing?
I will say, cancan is working for my user management and users controller for an admin to create, list and edit users, so I know cancan is working in general. It is also working for updating and deleting a users documents. It is just the index function not working.
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.id
if user.has_role? :user
can :create, Document
can :read, Document, :user_id => user.id
can :update, Document, :user_id => user.id
end
end
end
end
You have to make sure that non-logged in users, as well as users whose user.id isn't the same as the Document's user_id (document owner) don't have permission to read all Documents.
class Ability
include CanCan::Ability
def initialize(account)
user ||= User.new #non-logged-in user
# logged in users
if user.id and user.has_role?(:user)
#content owners
can :manage, Document, :user_id => user.id
#other logged-in users
can [:show, :create], Document
end
end
end
Be careful you don't have any line like can :read, :all or can :read, Document most likely you are giving the permission somewhere if you said cancan is working already.
In your case you should write in your ability class
def initialize(user)
can :manage, Document do |document|
document.user == user
end
end
This will check whether document belongs to logged in user or not. If yes can will return true otherwise false.
For more details on how to handle complex authorization with block,
https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks

Rails Can Can Ability Class For Multiple Devise Models

I was wondering how I can define an ability class and serve that ability class depending on the user that has logged in.
I am using Active Admin, Can Can and Devise and I have successfully created a User and an AdminUser models.
I have this in my ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if (user)
can :manage, Item
end
end
end
Now I have used this wiki entry to determine that we can indeed define a custom ability file and use that instead of the ability.rb:
https://github.com/ryanb/cancan/wiki/changing-defaults
But what I wanted to do is, be able to use ability.rb if a "non-admin user" is signed in and a custom abilty if a user admin is signed in.
Side Question: Could it be done such that I don't need a custom one and I could set permissions in one ability.rb file?
I've never really used ActiveAdmin, so I'm not entirely sure if I'm missing something, but it doesn't seem like that framework relies on CanCan. That's why I'm assuming you're defining a current_ability method like explained in the wiki and it's instantiated with Ability.new(current_user).
If that's the case, and your current_user can be either a User or an AdminUser, then there's no problem in checking for that in the Ability class:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.kind_of? AdminUser
can :manage, Item
elsif user.kind_of? User
can :read, Item
end
end
end
You can simply take a look at the user's type and change the rules accordingly. You can also use is_a? instead of kind_of? for stricter checking, but it's probably not required and might cause issues if you decide to do inheritance later on.
Another way you could check is by defining an admin? method in both models. This might be a better way to do it, since explicit type checking is not very popular in ruby -- it often limits your choices. It might look like this:
class User < ActiveRecord::Base
def admin?
false
end
end
class AdminUser < ActiveRecord::Base
def admin?
true
end
end
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.admin?
can :manage, Item
else
can :read, Item
end
end
end

Resources