How do I allow anonymous users to view the generated XML page for a model with Activeadmin?
../admin/categories.xml
I tried adding skipping the authentication filter with no success.
ActiveAdmin.register Category do
before_filter :authenticate_user!, :except => [:index]
end
Just an update if anyone finds this post. You have to set up Activeadmin with cancan.
https://groups.google.com/forum/?fromgroups#!topic/activeadmin/uJCkRkrrfHY
Remember to use the Activeadmin version from github. When this is configured you will have to initiate a dummy guest user - add this to application_controller.rb
def authenticate_admin_user!
current_user ||= AdminUser.new # guest user
end
Now you will have to configure your cacan permissions
class Ability
include CanCan::Ability
def initialize(user)
if user
can :manage, :all
else
can :read, Category
end
end
end
cancan screencast:
http://railscasts.com/episodes/192-authorization-with-cancan
Related
I am trying to use cancancan for authorization. When I am an authorized 'group_creator' user I am still denied access to groups/new.
Roles are functional and has_role? from rolify works. So I think the issue comes with cancancan or maybe devise.
Ability.rb
def initialize(user)
user ||= User.new # guest user (not logged in)
alias_action :create, :read, :update, :destroy, to: :crud
if user.has_role? :group_creator
can :create, Group
elsif user.has_role?(:creator, Group)
can :manage, Group, owner_id: user.id
elsif user.has_role?(:admin, Group)
can :crud, Group, :id => Group.with_role(:admin, user).pluck(:id)
else
can :read, Group
end
end
Relevant GroupsController.rb
class GroupsController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource
def index
#groups = Group.all # Can be deleted due to cancancan?
end
def new
#group = Group.new # Can also be deleted due to cancancan...
end
end
I have tried debugging in the console with:
user=User.last
user.has_role? :group_creator # returns true
group=Group.last
ability=Ability.new(user)
ability.can?(:create, Group) # returns false
ability.can?(:create, group) # returns false
Two things here.
The user needs :read AND :create ability to access new action. This solved this problem for me.
After fiddling with a fresh mind this morning some advice for others running across this that are new like me... Make sure to reboot server after altering ability.rb... (I am not sure if this was part of the issue yesterday but I thought I should mention it). Cancancan wiki has some explanation on how to utilize a separate permissions table for dynamic modification of abilities.
I am using the CanCan Gem and would like to assign a User two roles which conflict. I need a User to have two roles, one is the x role and the other is the y role. Role x allows users to create posts but not create articles. Role y allows users to create articles but not create posts.
My ability.rb file is like the following:
if user.role?(x)
can :manage, Post
cannot :manage, Article
end
if user.role?(y)
cannot :manage, Post
can :manage, Article
end
Currently if I assign a User both roles, the permissions for role Y will override the permissions for role x. I would like to allow Admins to stack roles so that if I want to add roles x and y to a User, that User will be able to manage Posts and Articles. So if the role has a can and another role has a cannot, the can permission overrides.
Shouldn't
if user.role?(x)
can :manage, Post
end
if user.role?(y)
can :manage, Article
end
be enough?
cannot just removes previously granted permissions. But if you do not grant them, then you do not need to remove them.
See also https://github.com/CanCanCommunity/cancancan/wiki/Ability-Precedence
Here is a running example:
require 'cancan'
class Ability
include CanCan::Ability
attr_reader :user
def initialize(user)
#user = user
if user.role?(:editor)
can :edit, Post
end
if user.role?(:reader)
can :read, Post
end
end
end
class Post
end
class User
attr_reader :name
def initialize(name, *roles)
#name = name
#roles = roles
end
def role?(role)
#roles.include?(role)
end
end
admin = User.new('admin', :reader, :editor)
user = User.new('user', :reader)
editor = User.new('editor', :editor)
admin_ability = Ability.new(admin)
user_ability = Ability.new(user)
editor_ability = Ability.new(editor)
def output(ability, permission)
puts "#{ability.user.name} can #{permission} Post: #{ability.can?(permission, Post)}"
end
output(admin_ability, :edit)
output(user_ability, :edit)
output(editor_ability, :edit)
puts "--"
output(admin_ability, :read)
output(user_ability, :read)
output(editor_ability, :read)
The default is to NOT HAVE a permission. So if you only work in "additive" mode where you add permissions if a user has roles, you will never need to remove one of them.
:manage is the same as [:create, :edit, :update, :new, :destroy, :index, :show] and is only there for convenience. If you only want to add 6 of those permissions, you can add all 7 and then remove 1. But other than that I don't think you'll need cannot for your example.
The accepted answer is now 5 years old, and this functionality appears to be in CanCanCan as expected by the OP.
It did not work as expected in version 1.15, but does work in version 3.3, so you may need to upgrade your cancancan gem.
I'm attempting to use Vanity URLs in my Rails app so that instead of an ID, the username is shown. I've created the slug so that the username is used in the url instead of the id (everything works here ok), the issue I'm facing occurs when I try to load a page where I have load_and_authorize_resource enabled in the controller. I believe this is attempting to find the user via the id instead of the slug which is causing the error "Couldn't find User with id=X". Is there somewhere I can override the load_and_authorize_resource so that it uses the slug and not the ID?
class User < ActiveRecord::Base
def to_param
slug
end
end
class UsersController < ApplicationController
load_and_authorize_resource only: [:dashBoard]
def dashboard
end
def show
#this is the user's profile page, because I don't have a load
#and authorize resource check on it, it loads without error
#when the vanity url is enabled
#user = User.find_by_slug(params[:id])
end
end
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.memberships.count > 0
can :manage, User
else
can :read, :all
end
end
end
I figured it out; adding find_by: :slug to the load_and_authorize_resource did exactly what I was looking for.
load_and_authorize_resource only: [:dashBoard], find_by: :slug
I want to "map" MyController to User model
#ability
class Ability
include CanCan::Ability
def initialize user
user ||= User.new
if user.has_role? :admin
can :manage, :all
else
can :read, :all
can :read, User do |u|
u && u.user_id == user.id
end
end
end
end
#routes
get 'my_controller/show/(:id)', to: 'MyController#show'
#controller
class MyController < ApplicationController
# load_and_authorize_resource
def show
# showing a user
end
end
So my_controller/show/(:id) can be accessible only for admin and current user. For example, the user with id == 2 can see the their own profile my_controller/show/2 and cannot others users' ones such as my_controller/show/1234 unless they are an admin.
There is no My model in the the project. Ideally, I have to rename MyController to UserController but I'm not allowed to do that for some reason.
If I uncomment load_and_authorize_resource at MyController, there will be an error of
NameError in MyController#show
uninitialized constant My
So how can I get rid of it?
You can specify the name of the type of resource to load and authorize:
load_and_authorize_resource :user
Otherwise cancan will attempt to work it out by convention (based on the name of the controller).
https://github.com/ryanb/cancan/wiki/authorizing-controller-actions
I have a User Model, with a admin boolean field. I then have an Admin Controller which I want CanCan On.
How do I add CanCan to the Admin Controller as there is not Admin Model?
I've tried:
class AdminController < ApplicationController
load_and_authorize_resource :user
load_and_authorize_resource :admin, :through => :user
class Ability
include CanCan::Ability
def initialize
....
can :manage, Admin if current_user.admin == TRUE
....
But that errors with "Access denied on nil"
Ideas? Thanks
Are you sure you have access to the 'current_user' method in your ability class? I wouldn't think you would have.
For what I remember when using CanCan you could have this in your Ability class:
def initialize(user)
user ||= User.new #guest user.
...
end
And the user would be the current user, I expect. And I guess that should work.
You can also take a look at this page: https://github.com/ryanb/cancan/wiki/Non-RESTful-Controllers of the CanCan wiki. It's not exactly the same issue, but as it covers a special case (Non-RESTful-Controllers) it might give you some hints about how to do what you want to do.
Cheers