Every repository with this icon (
Every repository with this icon (
| Description: | Yet another role-based authorization system for Rails edit |
-
12 comments Created 7 months ago by be9Add a method to auth objects to query about auth subjects with particular rolefeaturexQuote from Jaryl Sim:
is there any way we can retrieve users who happen to have role access to an object? For example, an object has 3 managers. Can we do something like object.managers? I know that this is beyond the scope of access control, but I think that this use case might happen often enough to be addressed in Acl9.
Comments
-
Something like:
access_control do allow all, :except => :destroy allow complex_role, :to => :destroy do is :strong is :decisive is :owner, :of => :object is_not :banned is_not :fake end endComments
-
I've seen the acl9 documentation referred to as "confusing" or "don't read the docs, just use the thing".
Currently the only doc is the huge README file. Actually it's more of a description what and how acl9 does. Would be enough for me if I weren't the creator, but... Different people learn things different way.
So, do you see any ways of improving the docs? What are the most unclear aspects? Should it be tutorials, or...?
Looking forward to your comments here.
Comments
I think tutorials like the acl9_example project would be a great idea. In my opinion you have to work with acl9 to understand all benefits of this plugin.
kevinansfield
Mon Jul 06 16:00:45 -0700 2009
| link
A bit of documentation on testing would be gladly appreciated! I realise the basic cases should be pretty simple, but for those new to testing, just working out the required fixtures can be a pretty big stumbling block
-
Some people expect ACL block in derived controller to extend its counterpart from the base controller. So they put rather restrictive rules to the base (e.g. deny all), trynig to loosen the restrictions in descendant controllers.
Unfortunately this doesn't work. Each access_control call with a block results in a filter being appended to the "before" filter chain. Now add more filters, get more restrictive behavior.
skip_before_filter comes to the rescue when you need to circumvent ACL block from the base controller, but how could we truly inherit ACL rules?
I see several possibilities.
Declare "virtual" ACL blocks, which are used only for inheritance. Something like:
class BaseController < ApplicationController # ... access_control :base, :virtual => true do deny anonymous end # ... end class DerivedController < BaseController access_control do extends :base allow anonymous, :to => [:show, :index] allow logged_in end end
Here :base block doesn't get installed in BaseController as a filter.
- Modification of (1).
Install the filter, but also save the rules into inheritable array. Each derived controller will append its rules, calling skip_before_filter against the inherited filter.
class BaseController < ApplicationController # ... access_control :base, :virtual => true do deny anonymous end # ... end class DerivedController < BaseController access_control :base do allow anonymous, :to => [:show, :index] allow logged_in end end class DerivedDerivedController < DerivedController access_control :base do allow anonymous, :to => [:custom] end endWe get 3 blocks here. The 3rd block is used to match first (both for allow and for deny). If it doesn't bring a match, the 2nd block is tried and then the 1st.
Comments
-
...make all the pieces into the wiki.
Comments
-
For those who don't need object roles -- dead-simple has_role?() backend.
Comments
-
Currently one needs to copy-paste it from the doc, but the generator will do well.
Comments
-
Currently there seems to be privilege revocation missing which results in orphaned data rows.
Example:@user.has_role! :provider, @service
If @service or @user is deleted, corresponding privileges need to be revoked. Maybe this could be implemented inside an after_destroy callback.
Comments
I'll try to provide one, soon. Just wanted to mention this – was not sure if I missed something.
-
Using the ACL9 roles table as a has_many :through link
5 comments Created 4 months ago by rurounijonesWell, it appears that you cannot reply to posts on the Google Groups without signing up, something I have no intention of doing (I like how they let you start a thread though...eugh).
Following on from :http://groups.google.com/group/acl9-discuss/browse_thread/thread/5b663c80191ac35a
I have the following
has_many :committee_memberships, :class_name => "Role", :finder_sql => 'SELECT * FROM roles r WHERE name = "member" AND authorizable_type = "Committee" AND id = (SELECT role_id FROM roles_users WHERE user_id = #{id} and role_id = r.id)'
This nicely returns all the role records for that user with the match. It is possible to use this to hardcode a "commitees" has_many without using the :through of users_roles but that isn't quite what I am after.
Has anyone got any ideas if this could be built on using a :through to get what I am after? Or any other ideas on how to get a :through working.
Comments
Oh my, this is bizarre :)
I think you can do this the other way around. Store committee memberships in a regular HMT and override User#has_role? method, like this:
class User < AR::Base has_many :committee_memberships has_many :committees, :through => :committee_memberships def has_role?(role, obj=nil) if role.to_s == 'member' && obj.is_a? Committee committees.include?(obj) else super end end end
rurounijones
Tue Jul 21 09:42:14 -0700 2009
| link
Hehe, I came to roughly the same conclusion. I changed the HABTM between users and roles to a HMT so that user has_many :roles and I am trying to get a :through through that but my inexperience with polymorphic HM is tripping me up a bit.
I have a fork of acl9 with my changes in it and I am working on something like the above, will take me a while though I think as I have a lot to understand.
rurounijones
Tue Jul 28 07:47:22 -0700 2009
| link
Looks like the has_many_polymorphs plugin/extension works here.
Cool. Do you have any working code we could put into a tutorial?
rurounijones
Tue Jul 28 21:43:26 -0700 2009
| link
Not with the original version of acl because of the HABTM relationship between subjects and roles. has_many_polymorphs will only work where the subject/role relationship is a normal HM and the relationship between subjects and objects is HMT via the roles.
-
Roles are great, but it would be awesome to be able to control authorization based on associations that already exist, without having to manually assign a role to a user. For example, let's say a User created a Post, so
@post.creatorreturns the user that created it. I want to be able to do this:allow :creator, :of => :postwithout calling
user.has_role!('creator', post).I know that you can override
#has_role?, I currently do that to achieve this. I just thought that this could be a rather common issue. My implementation also allows for the same role to be applied to other subjects (users, in this case), so it doesn't get in the way of anything else you would do.What do you think? Here is my version of
has_role?def has_role?(role_name, object = nil) !! if object.nil? self.roles.find_by_name(role_name.to_s) || self.roles.member?(get_role(role_name, nil)) else role = get_role(role_name, object) subject_owns_object = object.send(role_name) == self if object.respond_to?(role_name) (role && self.roles.exists?(role.id)) || subject_owns_object end endComments
-
I have:
class User < ActiveRecord::Base acts_as_authentic do |c|
c.transition_from_restful_authentication = trueend
acts_as_authorization_subject end
class Role < ActiveRecord::Base acts_as_authorization_role end
All works fine except that user.roles that give me method_missing error. I need to put habtm roles relation in the User class.
What I am missing ?
Comments
-
Issue with action block when allow anonymous and another role
0 comments Created 17 days ago by franckI run into a bug with the dsl when using action blocks.
This work :
access_control do allow :superadmin action :index, :show do allow anonymous end endThis doesn't :
access_control do allow :superadmin action :index, :show do allow anonymous allow :member end endAfter some testing, the wrong expression is :
.(@_subject.nil?) || (!@_subject.nil? && @_subject.has_role?('member', nil)) && Set.new(['index','show']).include?(@_current_action)As you can see, when anonymous is used, this expression always true.
This issue come from missing parentheses in
_either_offunction.I correct it like so, and it works :
def _either_of(exprs) clause = exprs.map { |expr| "(#{expr})" }.join(' || ') return "(#{clause})" endI'll fork acl9, add few tests, and commit the correction.
Cheers
FranckComments












Currently, is there any way we can do this ourselves?
Jaryl,
Basically, @object.users (if your subject is User) gives you all users which have gotten any role on the @object. Seems it was undocumented.
For querying by role name please see this: http://gist.github.com/115944
What about using something like http://technicalpickles.com/posts/using-method_missing-and-respond_to-to-create-dynamic-methods
To create and define dynamic methods based on roles in the system. I am having the same issue and just started investigating this possibility.
Another possibility is to change the has_and_belongs_to_many User/Role relationship to has_many? Then use a has_many :through relationship to link users to their objects, this could save some coding and leverage the built-in rails HMT code but not sure how easy it would be.
@rurounihones, I believe that's how the author of this gem has implemented it.
Yea but @object.users is rather restrictive isn't it. I am talking about being able to do (Assuming you have the roles admin, member, editor in the roles table) things like @object.members, @object.editors, @object.admins which only returns the associated users. I have added the code I have so far (Which appears to be working) to a fork of http://gist.github.com/115944
The code needs to be cleaned up and modularized but it appears to work.
Hmm, I believe that in acl9, you only get to call @object.users if your subject is called User. So if you had subjects such as Admin, Member and Editor, you will be able to call @object.admins, @object.members and @object.editors.
I don't have time to verify if this is actually how acl9 works, but that is what the author is suggesting it does. In terms of its implementation, he might have used method_missing as your link suggests, or dynamically-generated code.
No, you cannot currently call @object.admins or anything apart from @object.users (which is hardcoded in model_extension.rb) in vanilla ACL9 which is why I am writing the method_missing way of doing it.
Speaking of which, it iis now working pretty efficiently as far as I can tell with User/Role model names but I am not sure how I can make those dynamic so am hoping be9 will have a look at the gist and change what needs to be changed.
Perhaps you are talking about an older version of the code. The current one does not have any hard coding as far as I can tell. The 'relationships' are created dynamically based on the subject tables' names.
From model_extension.rb
That is the code that sets up the @object.users undocumented relattionship as mentioned in a previous post. The only dynamic thing about it is that it allows for you to user a difference class to the User class. That is it, nothing else, certainly nothing like dynamically returning user lists based on roles entered which is why be9 put the original GIST up which I a forked with the method_missing way of doing things.
Ah, okay my bad, I didn't get what you were trying to do at first.
So your code dynamically generates methods based on the role names, retrieving the listing of objects (based on be9's code). Pretty good too. Now all we have to do is get the author to integrate this so that we don't have to do the plumbing for each time.
You're welcome with pull requests ;)
If someone gets to work on that before that I do, an other thing that'd be nice would be to be able not only to get users having one specific role. But all the ones having one or many roles.
For example @object.admin_and_manager
For the users having the role "admin" and the role "manager".
Or @object.not_banned
For every user except the ones having the role "banned".