I have installed rails_admin gem without any error its display models crud too,but i have requirement in which i need to show current_user logged in associated data
e.g User has many Books so in rails admin i want only that user book but currently it's showing all users books which is default behaviour of rails_admin
i have also try to use cancancan gem for achieve same thing but its not working my rails_admin initializers config as below
rails_admin.rb
RailsAdmin.config do |config|
### Popular gems integration
## == Devise ==
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
config.parent_controller = 'ApplicationController'
## == Cancan ==
config.authorize_with :cancan,UserAbility
## == Pundit ==
# config.authorize_with :pundit
config.included_models = ["Book","User"]
config.actions do
dashboard # mandatory
index # mandatory
new
export
bulk_delete
show
edit
delete
show_in_app
end
end
UserAbility Class is implemented as below
class UserAbility
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
if user.present?
can :access, :dashboard
can :manage, :Book,id:user.id
end
end
end
Instead of can :manage, :Book,id:user.id, try using:
can :read, Book, user_id: user.id
So the abilities together look like:
can :access, :rails_admin
can :dashboard
can :read, Book, user_id: user.id
I think you're misunderstanding the scope of Rails Admin. In essence, it's a snapshot of your database, and is meant for more administrative operations like querying your database for something specific.
The only thing you'd reasonably be able to do is to look up all Books for a given user, with the default falling to all books for all users. Filters exist within the display to be able to narrow down based on a user's specific credentials, such as user name, email, or ID.
For a conceptual check, a user in Rails Admin isn't treated or regarded the same as a user in your application. Instead, think of using Rails Admin as a way to check the data in your database as opposed to showing data for a specific, authenticated person.
As you describe, the more appropriate Rails way to do this would be to create a controller and route for this data, and to simply use current_user.books to get all of the books for the current user.
Related
I am using Rails Admin gem as an admin dashboard in my rails app, it works perfectly and shows all my models. Am using devise for authentication and have two types of users, Users that signup and devise guest user (users are saved till they sign up or sign in as guest user with an example email). In rails admin Users section, it shows all of the users even the guest user. I want to hide this guest user from there.
What i tried:
user.rb
scope :verified, -> { where(guest: false) }
rails_admin.rb
config.model User do
list do
scopes [:verified]
end
end
it did not work...is there any way to use permanent filters here as my normal users have many fields like location and username...so am thinking of doing something like showing only users who have username.
What you tried would filter the guest users on the list, not the access to the list itself.
The rails admin recommended way to solve this is with an authorization framework, see the cancancan documentation to get it working.
https://github.com/sferik/rails_admin/wiki/Cancancan
I successfully configured this per user.
Example of how it would work:
class Ability
include CanCan::Ability
def initialize(user)
return unless user && user.admin?
can :access, :rails_admin # only allow admin users to access Rails Admin
can :read, :dashboard # allow access to dashboard
if user.role? :superadmin
can :manage, :all # allow superadmins to do anything
elsif user.role? :manager
can :manage, [User, Product] # allow managers to do anything to products and users
elsif user.role? :sales
can :update, Product, hidden: false # allow sales to only update visible products
end
end
end
I need help to configure CanCanCan using ActiveAdmin. I have everything else working including devise. I can restrict menus using devise but if you know the URL lets say for edit you can still edit that resource. I want to restrict a normal user from editing/creating any resources but it does not seem to work.
Active_Admin.rb
config.cancan_ability_class = ActiveAdmin::CanCanAdapter
Ability.rb (simple out of the box)
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, Student
else
can :read, Student
end
end
end
User model.
admin:boolean
and if I login with a user who is not an admin i can still create/edit/delete, I just want to restrict them to read only.
Please help i am struggling with this only feature that I need to complete.
Thanks in advance
Change this thinks:
config.authorization_adapter = ActiveAdmin::CanCanAdapter
config.cancan_ability_class = Ability
authorization_adapter tells active admin which adapter it should be use.
cancan_ability_class tells the adapter which class it should use.
If that still doesn't work, try to rename Ability to AdminAbility.
I have Rails_admin installed with devise and I want to restrict the /admin dashboard to only admins. For the moment my code looks like :
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
As you can see users can get in to the dashboard so I want only the users with a boolean true in the admin column of the user table to get access to the dashboard.
How would you suggest I do this ?
If you dont want to use cancan you can do this:
config.authorize_with do
redirect_to main_app.root_path unless current_user.try(:admin?)
end
I use this and it works fine.
I would recommend you to use an authorization gem called cancancan (is the updated version of cancan) it's super easy to use and it will let you to give certain permissions to different kind of users. If you don't know nothing about this gem i will recommend you to see this railscasts that will teach you how to use it properly.
So after you installed the cancancan gem in the ability.rb file you just need to do something like this to limit the admin access
models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user && user.admin?
can :access, :rails_admin # only allow admin users to access Rails Admin
can :dashboard
can :manage, :all
else
can :read, :all # allow everyone to read everything
end
end
end
And don't forget to tell to the rails_admin gem that you are using cancancan to validate the authorization
config/initializers/rails_admin.rb
RailsAdmin.config do |config|
## == Cancan ==
config.authorize_with :cancan
end
To user the "user.admin?" method you must create it into the user model, but it will only work if you have a role model that has_many users and users belongs_to role otherwise you will need other way to verify the role, so it will be something like this
models/role.rb
has_many :users
models/user.rb
belongs_to :role
def admin?
role_id == 0 # If you have id == 0 for admin
end
Also i will recommend you to use a role model or enum to manage the different roles with ease.
I hope it helps :D
I want to give rights to users in my rails app. I have 'admin' who can create, update and delete all posts and comments, 'user' who can create and update only his own comments, and 'guest' who can do none of these. For this I use the gems 'devise' and 'cancancan'. I understand the 'devise' gem, but I don't understand 'cancancan'.
In the class ability.rb, how can I write rights for these users (admin, user, guest)?
Cancancan lets you only define permissions for given context. This context might be a user role which is not a part of cancancan and hence roles have to be defined by yourself.
There are various ways to define user role, e.g.
as a Role model,
Rails enum,
as suggested here,
as a string attribute of User model.
It all depends of the use case. An example of how to define abilities can be found here. In your case, it would look like:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.reviewer? #Just a logged user
can :manage, Comment, { owner_id: user.id }
elsif user.admin?
can :manage, :all
end
end
end
class User < ActiveRecord::Base
enum role: [ :reviewer, :admin ]
end
You can refer following rails cast http://railscasts.com/episodes/192-authorization-with-cancan
If you are going to use Roles, consider the Canard gem (https://github.com/james2m/canard) which combines CanCanCan with RoleModel (https://github.com/martinrehfeld/role_model). This gives you a well organized way of stipulating roles and their abilities
For example, if you have a user model, you would set the roles as follows:
class User < ActiveRecord::Base
acts_as_user roles: [:supervisor, :manager, :writer]
end
Then you can create Ability files for each role, including a base User (not assigned any roles) and Guest (not logged in)
Canard::Abilities.for(:user) do
can :manage, User, id: user.id
cannot [:destroy], User
end
The above will allow a user to update their own information but will not allow them to delete themselves. They also will not have access to any other user record.
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