I am trying to get Cancan to work with Devise on my Rails application. I tried to follow the directions here to set it up:
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/
I am stuck as I am getting the following error:
ArgumentError in Users::RegistrationsController#new
wrong number of arguments (2 for 1)
app/models/ability.rb:7:in initialize'
app/controllers/users/registrations_controller.rb:6:incheck_permissions'
My ability.rb reads as follows:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.role? :super_admin
can :manage, :all
elsif user.role? :admin
can :manage, :all
elsif user.role? :user
can :read, :all
# manage products, assets he owns
can :manage, Product do |product|
product.try(:owner) == user
end
can :manage, Asset do |asset|
asset.assetable.try(:owner) == user
end
end
end
end
My registrations controller reads:
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :check_permissions, :only => [:new, :create, :cancel]
skip_before_filter :require_no_authentication
def check_permissions
authorize! :create, resource
end
end
This only occurs on the signup page. All other pages within the app are working fine.
When using cancan u have to use following line in your controller.
load_and_authorize_resource
Related
I have 2 tables: posts and users(their relation is many-to-many), User has many favorite_posts(with FavoritePost table(it consists of user_id and post_id).
So, i have a route:
get 'favorite_posts', to: 'favorite_posts#index'
(users/:user_id/favorite_posts)
In my ability.rb:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.new_record?
can :read, [Post]
else
can :read, [Post]
can :manage, [Post], owner_id: user.id
can :manage, [FavoritePost], user_id: user.id
end
end
end
In my controller(favorite_posts_controller.rb):
class FavoritePostsController < ApplicationController
load_and_authorize_resource through: :current_user
def index
#favorite_posts = User.find(params[:user_id]).favorite_posts
end
So, i need to block redirect to pages with favorite posts of other user through ability.rb. What i need to do?
Take a look at this quote from a CanCan maintainer:
CanCan can answer the question whether the user can or can't do
something, but what the app does from there is very context specific
and I don't think is a good fit for the ability.rb file.
If you don't want to let other users view the current user's favorite posts, it's best to put this in a before_action filter in your favorite_posts_controller:
class FavoritePostsController < ApplicationController
load_and_authorize_resource through: :current_user
before_action :correct_user, only: [:index] # add any other actions you want
def index
#favorite_posts = current_user.favorite_posts.all
end
private
def correct_user
user = User.find(params[:user_id])
redirect_to root_url unless current_user && current_user == user
end
end
I want the Admin user to not have the ability to create users with the role of Super Admin but still be able to create other Admins and Regular Users. How do I accomplish this? Here is my Ability.rb:
class Ability
include CanCan::Ability
def initialize(user)
if user.super_admin?
can :manage, :all
elsif user.admin?
can :manage, [Article, Comment]
can [:destroy, :update], User, :role_id => 2 # If Admin
can [:destroy, :update], User, :role_id => 3 # If User
can :read, User
can :create, User
elsif user.user_regular?
#cannot :read, ActiveAdmin::Page, :name => "Dashboard"
#can :manage, :all
end
end
end
Use cannot with in admin block like cannot :creat, User, :role_id => 1 # let 1 is super admin role id. You can get more info about combine ability at here
I use the CanCanCan, Devise and Rolify gem to for authentication and permission management. But when I create a new controller I got this message:
NameError in PanelController#dashboard
uninitialized constant Panel
My PanelController:
class PanelController < ApplicationController
load_and_authorize_resource
def dashboard
end
end
When I remove this line: load_and_authorize_resource
the Route works. But I can access it without authentication. Do I need a PanelModel to use it?
My AbilityModel is this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
alias_action :create, :read, :update, :destroy, :to => :crud
if user.has_role? :admin
can :manage, :all
elsif user.has_role? :user
can [:read], User
can [:update, :edit], User do |account|
account.email == user.email
end
else
# can :read, :all
can [:create, :new], User
end
end
end
Yesterday my Code works great but today I don't know why I get this error.
Maybe anyone can help me.
My Routes are this for the Controller:
devise_scope :user do
authenticated :user do
# Rails 4 users must specify the 'as' option to give it a unique name
root :to => "panels#dashboard", :as => :panel
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
You can use CanCanCan without a corresponding model using authorize_resource :class => false like this
class PanelController < ApplicationController
authorize_resource :class => false
def dashboard
end
end
and then in your ability:
elsif user.has_role? :user
can :dashboard, :panel
I have an app that is using CacCan and Devise. I am having Devise handle the User destroy action
The route
DELETE /users(.:format) devise/registrations#destroy
My Controller
class UsersController < ApplicationController
skip_before_filter :authenticate_user!, :only => :portfolio
def index
redirect_to dashboard_user_path(current_user)
end
def dashboard
...
end
def portfolio
end
end
My ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role?('Administrator')
can :access, :rails_admin
can :dashboard
can :manage, :all
else
cannot :destroy, User
can :read, :all
...
end
end
end
This code above does not work. A user who is not an administrator still has the ability to delete a user. I am assuming the reason is that I do not have UsersController#destroy method.
So my question is, How do I make CanCan prevent a user who is not an administrator from being able to delete a user?
Any help would be greatly appreciated.
Thanks
It seems to me that you defined abilities but not use them at all.
I suggest to read at least this (gem has a reach wiki with very useful information so it worth to read all articles).
I prefer to use powerful load_and_authorize_resource but in you case maybe enough authorize! (code is NOT tested!)
def destroy
#user = User.find(params[:id])
authorize! :destroy, #user
...
end
I have Projects resource which is nested in Users resource.
My Cancan Ability class is:
class Ability
include CanCan::Ability
def initialize(user)
#everyone
can :read, Project
if user.blank?
# guest user
...
else
#every signed in user
case user.role
when User::ROLES[:admin]
#only admin role user
can :manage, :all
when User::ROLES[:member]
#only member role user
can :update, User, :id => user.id
can [:create, :update, :destroy], Project, :user_id => user.id
else
end
end
end
end
And Projects controller:
class ProjectsController < ApplicationController
load_and_authorize_resource :user
load_and_authorize_resource :projects, :through => :user, :shallow => true
...
end
I have few questions:
Is it possible to deny :read User and allow to :read Project, so that everyone could access /users/10/projects, but not /users/10 or /users?
How can I deny user accessing :new action with other user_id? For example, if I add
#everyone
can :read, User
can :read, Project
this code allows user with id 42 to access /user/41/projects/new.
Solved it by doing:
class Ability
include CanCan::Ability
def initialize(user)
#everyone
can :read, Project
can :read, User # required to access nested resources
cannot :index, User
cannot :show, User
if user.blank?
# guest user
...
else
#every signed in user
case user.role
when User::ROLES[:admin]
#only admin role user
can :manage, :all
when User::ROLES[:member]
#only member role user
can :update, User, :id => user.id
can :manage, Project, :user => { :id => user.id }
else
end
end
end
end