I am new to Rails and am having troubles figuring out how to create user roles and then have it working with Cancan. I am following rails cast on this and the cancan wiki. What I don't understand to do is define each user role, for example what the admin, registered member and guest can access. I'm not sure if I'm on the right path or not with my coding. I have also run into a "undefined local variable or method `roles_mask'" error.
I don't believe I have the roles set proper in the below file. I have created user authentication from scratch if that helps any. The sections I have so far are galleries and user profile. ATM if I create a new account and select drop down box option "admin", I don't have any admin powers. I am still lock out of accessing pages.
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if #user && #user.role?(:admin)
can :manage, :all
else
can :read, :all
end
if user.role? :user
can :manage, Profile
end
if user.role? :admin
can :manage, Profile
end
end
end
user.rb
ROLES = %w[admin user guest banned]
def roles=(roles)
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
end
def roles
ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
end
def role?(role)
roles.include? role.to_s
end
In your ability.rb file,
if #user && #user.role?(:admin)
should probably be
if user && user.role?(:admin)
Related
class Ability
include CanCan::Ability
user ||= User.new # guest user (not logged in)
if user.admin
can :manage, :all
else
can :read, :all
end
end
I am using has_many through association. Having 3 tables - User, Role and UserRole. UserRole table is used to connect users and roles tables. In UserRole table I am storing user_id and role_id. There is no attribute named admin. How do I change the above code to check if the user is admin?
consider your role table has field 'name' and it have content some thing ('admin','guest',etc)
open your model app/models/user.rb and add method below
def admin?
self.roles.find_by_name('admin') ? true : false
# since one user has many roles you should find by role name
# whether it has role with name admin
# if it find the record the method will return true
end
in your ability.rb you can set like follow
class Ability
include CanCan::Ability
user ||= User.new # guest user (not logged in)
if user.admin? # I changed admin to admin? to match method above
can :manage, :all
else
can :read, :all
end
end
I am using cancan to manage authorizations in an activeadmin environment. I have recently used the active_skin gem to improve the looks, but only the super admin with manage:all access could see the new looks. May I know how I could make it visible to others?
Here is a sample Ability file:
if user.is? :admin
can :manage, :all
else
# Admin users can only manage their own posts
can :manage, Post, :organization_id => user.organization_id
end
1- You can use this
can :read, :all
2- Suggest you use new CanCanCan asCanCan no longer updated. Switching is no drama
Pierre
in my application for the User model I have an attribute username (should probably be name). Username is the name the user signs in with. In the sample code below I check if the current user is admin level and then if the username == admin they can manage all else they can only read all. The puts statements are for checking purposes.
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user
if user.is? :admin
puts "-------"
name = user.username
puts "username = " + name.to_s
puts "-------"
if name == "admin"
can :manage, :all
else
can :read, :all
end
elsif user.is? :user
can :manage, Drill
There is only admin interface in my app and I use AdminUser model. The admin users can have different roles.
I want to change the resource retrieval based on admin role. I added to my ActiveAdmin register block:
#app/admin/payments.rb
scope_to :current_admin_user
And I expect I could write something like:
#app/models/admin_user.rb
def payments
case self.role
when role == 'manager'
Payments.where('...')
when role == '...'
end
end
But this doesn't work and always shows all the resources.
Any idea how can I get this work?
Finally, I used the scoped_collection method
ActiveAdmin.register Payment do
...
controller do
def scoped_collection
#roles which need to be scoped
if current_admin_user.role == 'accountant' or current_admin_user.role == 'manager'
resource_class.send(current_admin_user.role)
end
end
end
And then just define the scopes in the model:
class Payment < ActiveRecord::Base
scope 'accountant', where('...')
scope 'manager', where('...')
...
end
I found the better solution, then.
Authorization adapter do just fine, and there is not need for scopes. For example, with CanCan:
class Ability
include CanCan::Ability
def initialize(user)
#read/manage actions
if user.role == 'manager'
can :manage, Payment, :accessible_by_manager => true
elsif user.role == 'accountant'
can :read, Payment, :accessible_by_accountant => true
else
#can read all
can :read, Payment
end
end
end
I am working on a rails application and it requires two different types of roles. One is Employee and other is Admin.
Cancan documentation says that it assumes there is a user or current_user method in the application.
So how can I use cancan to set roles for employee and manager in my app ?
Do like this
write this in application helper
def is_employee?(user)
emp_role = Role.find(:first, :conditions => ["name = ?", "Employee"])
return user.roles.include?(emp_role)
end
def is_admin?(user)
admin_role = Role.find(:first, :conditions => ["name = ?", "Admin"])
return user.roles.include?(admin_role)
end
And abily look like this
class Ability
include CanCan::Ability
include ApplicationHelper
def initialize(user)
# Define abilities for the passed in user here. For example:
#
user ||= Employee.new # guest user (not logged in)
if is_admin?(user)
can :manage, :all
# cannot :manage, IpAddress
elsif is_employee?(user)
#your code
end
For define roles see it
http://stackoverflow.com/questions/10222400/rails-adding-an-admin-role-using-devise-who-can-see-all-the-users/10222813#10222813
It sure works...
In my app I have the following models:
Users
Groups
Permissions (user_id, group_id, role_id)
Where role_id 1: admin, 2: member
I want to make sure I'm understanding CanCan correctly. In the ability.rb file, I only want group admins (permission.role_id == 1) to be able to update/destroy/create new group permissions.
permission.role_id == 2, members, should just be able to read the group and the group's permissions. Except for having the ability to destroy their group permission.
Here is my CanCan ability.rb file:
class Ability
include CanCan::Ability
def initialize(current_user, groupid_viewing)
current_user ||= User.new #Guest user (not signed in)
if groupid_viewing && current_user.try(:role, groupid_viewing) == 'Admin'
can :manage, Group
can [:create, :update], Permission do |permission|
current_user.try(:role, groupid_viewing) == 'Admin'
end
class GroupsController < ApplicationController
....
def current_ability
#current_ability ||= Ability.new(current_user, params[:group_id] && params[:group_id].to_i)
end
class ApplicationController < ActionController::Base
def current_ability
#current_ability ||= Ability.new(current_user, nil) #(user, group)
end
You also need to specify the abilities for the role_id:2.
if groupid_viewing && current_user.try(:role, groupid_viewing) == 'Member'
can :read, Group
can :destroy, Permission do |permission|
current_user.try(:role, groupid_viewing) == 'Member'
end
Also, there is no need of creating current_ability the way you are doing.
It should be an after_create callback that should assign abilities when the Member or Admin is created.