I'm working on a project where I'm trying to use lit https://github.com/prograils/lit to organise my translation file. So I've installed the gem and done the it's working. The problem is that the dashboard is now available to any user.
We use devise for authentication and pundit for authorization, but I can't find any mechanism to restrict access to the dashboard depending on the users role.
Any help would be greatly appreciated.
dashboard depending on the users role. is something you need to achieve using(in your case) Pundit. As you mentioned you are already using it then you should be able to do something like below:
class DashboardPolicy
:
:
:
def show?
user.admin?
end
end
In you user.rb model you will need a method which would return a boolean value something like:
def admin?
self.role == "admin"
end
Update (in case of no access to controller method)
As you mentioned you dont have access to the controller method then in this case you may want to check for constraints at the routes level.
I wont be adding code snippets here since it has been documented really well on another question you can check out the answer here: https://stackoverflow.com/a/29136866/2545197 and also read more about the same here: http://guides.rubyonrails.org/routing.html#advanced-constraints
Related
Afternoon, got a bit of an issue I am not sure how to resolve.
I am trying to setup some rules that allows only certain types of user roles to update the status attribute on a model to a certain status.
So I looked into doing this with pundit as it seems to be an authorisation issue, however one problem with that is you cannot pass the params to the pundit policy which I would need access too (so I can see what attribute they are trying to change to), and it seems that its bad practise to pass params to a pundit policy.
The next option was to make it a callback in the model, however the problem here is I don’t have access to the current_user inside the callback and again it seems its bad practise to add the current_user helper into a model.
So I am left with perhaps doing it in the controller? Again does not seem the right place for it?
An example to make it a little easier to understand:
I want to allow a User with the role of admin to be allowed to change the status of a post to "resolved", no one else is allowed to change the status to "resolved"
Try this,
create a instance method in User model like bellow,
def is_admin?
self.has_role(:admin) # if you are using rolify
---OR---
self.status == "admin" # if you have status attribute in your user table
end
Then call this method on current_user in edit/update method of post controller. to check current_user is admin or not
Im using a forum engine called Thredded. The installation goes well but when trying to access localhost:3000/forum , it gives me this error.
I already trying the suggested solution by adding a method admin? on user.rb but still it doesnt work.
def admin?
has_role?(:admin)
end
any ideas? thanks
Thredded maintainer here.
What version of the Gem are you using, by the way?
For the time being, if you haven't solidified how you would like your users' roles to be defined, I would consider making that method as simple as possible. For example - if the current user has an id of ... 4? or 5? Or whatever your personal user record id is - return true. Otherwise false.
Ask your user object if they are you! :)
def admin
self.name == 'Joel'
end
If the current user record has my name - then yes, I am an admin.
If there's anything I can do to help, please feel free to head over to the issues and open up a ticket. We'd be more than happy to help.
It looks like the missing method is admin, not admin?. Try defining that method instead:
def admin
has_role?(:admin)
end
In my project, i have pretty common namespace "admin".
namespace :admin do
resources :users, except: :show
end
I use Pundit gem to set proper authorization, but i found it difficult to use with controllers within namespace. my policies are organised as below
-policies
-admin
user_policy.rb
application_policy.rb
admin_policy.rb
awesome_policy.rb
very similar to controllers.
However, when inside the controller i use "authorize" method i get nothing but an error, informing that app is "unable to find UserPolicy". My UserPolicy looks like this:
class Admin::UserPolicy < AdminPolicy
end
So what is the problem, what should I do to make Pundit see those policies inside namespace?
Short answer: you can't make Pundit use controller namespace-specific policies.
Long answer: Pundit looks at the resource (model) to determine which Policy class to use, so any time you pass an instance of the User model in as the resource, it's going to look for UserPolicy, not Admin::UserPolicy
See here, here and here.
You could specify a policy class on your User model, but this doesn't really solve your namespaced controller issue since Pundit is going to derive the policy class from the model, regardless of where you're authorizing.
With the new merged commit you can do this.
It will work automatically.
UPDATE:
From 0.3 version is effectively removed without replacing feature. However namespace feature can be obtained in namespace branch on github.
You can see the discussion of feature in issue on github.
My suggestion for people who want use namespaces with pundit - don't use yet. Make before filter to access restricted area like admin dashboard and leave authorization model rules in pundit files. That's way you will be able to use pundit without hacks and problems.
While onemanstartup mentioned that is should work automatically now, I wasn't able to get the namespaced policy to work, but here's what I did find to be acceptable.
In your case, in the AdminPolicy, I added custom action names, like
def new_user?
some code
end
and then in my Admin::UserController#new action
def new
authorize #user, :new_user?
end
Just came here because of the same problem. Working with pundit v2.1.0, this is possible by overriding policy_scope and authorize in the controller. What I did for a similar setup:
module Admin
class ModuleController < ModuleController
private
def policy_scope(scope)
super([:admin, scope])
end
def authorize(record, query = nil)
super([:admin, record], query)
end
end
end
And then just use the usual ways of working with your policy in your controller, which will then take the policy from your Admin namespace.
This is also described in the README at https://github.com/varvet/pundit#policy-namespacing
In case you need more context than just the current user and the record, Pundit policies with two input parameters will be helpful.
I'm new to RoR and am utilizing CanCan for authorization. I'm wondering if I have to be explicit with every single ability that a user may have.
I'm probably not being clear enough, so I'll post some code to help illustrate my question.
if user.is_admin?
can :manage, all
end
if user.is_director?
can :update, Camp
end
In this case, would the director only be able to update a camp? Or would I have to denote what he/she specifically cannot do as well?
Thanks in advance.
If you added check_authorization to your ApplicationController, then yes, it will default to be locked down for all controller actions, unless specifically overwritten by skip_authorization_check.
See this GitHub discussion around this issue.
If I remember correctly the moment you implement CanCan you have to explicit, as long as you call the authorize_resource (or load_and_authorize_resource) in the matching controller.
So yes (, if you call one of authorize methods in the CampController).
(Also the director role should not overlap with the admin role ;) If it does it just get all permissions. And isn't it :all?)
I need to create roles based permissions systems in my Rails app. I would be totally happy with CanCan, but the main problem - it has to be dynamic, so that Admin has to be able to assign permissions and to create new roles. The permissions can be simple controller/action restrictions, and can be data related, for example some users can edit only their own profiles, and some of them can edit the profiles of all the users in the particular group. And it would be really nice to allow Admin to create new permissions.
What I'm thinking about is to store in db a controller/action, and some data related restrictions (I'm really confused here about the way to define them). So could you please give me some advice, what would be the best way to organize permissions?
Any thoughts are much appreciated
If you like CanCan, then I think is best to use it. Here is a short tutorial about storing abilities in database so non-programmers can update them:
https://github.com/ryanb/cancan/wiki/Abilities-in-Database
If you really, really want to implement such system yourself. Depending on your needs, I will suggest for you to implement it as simple as possible.
In the case you need only users to have access to modules(certain controllers). You can do:
Store all users permissions in just like serialized fields -> http://apidock.com/rails/ActiveRecord/Base/serialize/class
class User
serialize :permissions, Array
def access_to?(module)
permissions.include? module.to_s
end
end
some check when setting this field would be nice.
Just make a check on top of every controller if the current user have access to this controller(section)
class ApplicationController
private
def self.require_access_to(module)
before_filter do |c|
unless c.send(:current_user).try :access_to?(module)
c.send :render_no_presmissions_page
end
end
end
end
class AdminNewsController
require_access_to :news
end
Of course this is just a start position, from where you can easily evolve.
[EDIT The link given by #RadoslavStankov is a better answer than this.]
You can do it with CanCan easily. Just make a model for permissions (which has_and_belongs_to_many :users), and in your Ability#initialize load the permissions appropriate to the user from the model and say that the user can do them. Then make appropriate user interface for administrating that model.
Something like this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
user.permissions.each do |permission|
can permission.symbol, permission.scope
end
user.prohibitions.each do |permission|
cannot permission.symbol, permission.scope
end
end
end
where scope returned something like :all for nil scope, or Object.const_get(#scope_name) otherwise... Play with it. Anyway, it's doable.
More complex CanCan things are likely to be more complex (duh) - for example conditional permissions - but that would be a bitch to administer as well, so I think this should be enough for most applications.