I'm trying to add authorization to a rather large app that already exists, but I have to obfuscate the details a bit.
Here's the background:
In our app we have a number or roles that are hierarchical, roughly like this:
BasicUser -> SuperUser -> Admin -> SuperAdmin
For authorization each User model instance has an attribute 'role' which corresponds to the above.
We have a RESTful controller "Users" that is namespaced under Backoffice. So in short it's Backoffice::UsersController.
class Backoffice::UsersController < ApplicationController
filter_access_to :all
#... RESTful actions + some others
end
So here's the problem:
We want users to be able to give permissions for users to edit users but ONLY if they have a 'smaller' role than they currently have. I've created the following in authorization_rules.rb
authorization do
role :basic_user do
has_permission_on :backoffice_users, :to => :index
end
role :super_user do
includes :basic_user
has_permission_on :backoffice_users, :to => :edit do
if_attribute :role => is_in { %w(basic_user) }
end
end
role :admin do
includes :super_user
end
role :super_admin do
includes :admin
end
end
And unfortunately that's as far as I got, the rule doesn't seem to get applied.
- If I comment the rule out, nobody can edit
- If I leave the rul开发者_开发技巧e in you can edit everybody
I've also tried a couple of variations on the if_attribute:
if_attribute :role => is { 'basic_user' }
if_attribute :role => 'basic_user'
and they get the same effect. Does anybody have any suggestions?
I'm sure you solved this problem by now, but we just had a similar issue and hit upon a solution that may be of some help. It may not be possible to handle the case purely in the declarative authorization DSL but you can leverage the DSL to do the right thing in your models and views. Basically, we needed access to the role hierarchy graph.
The clue is that declarative_authorization has a nifty controller which produces a graph showing the hierarchy of your roles. Using the same supporting code they have, you can easily access the ancestors of any role thusly:
class Role < ActiveRecord::Base
require 'declarative_authorization/development_support/analyzer'
has_many :assignments
has_many :users, :through => :assignments
validates :name, :presence => true
validates :name, :uniqueness => true
def ancestors
Authorization::DevelopmentSupport::AnalyzerEngine::Role.for_sym(self.name.to_sym,
Authorization::Engine.instance).ancestors.map { |r| r.instance_variable_get("@role") }
end
def self_and_ancestors
ancestors << self.name.to_sym
end
end
You can then use this to do things like only offer role selections in the User editor which are the same or inferior to the current_user's role and also deny access or not permit the change in the model to someone trying to promote a user inappropriately. It's not that useful in the context of the declarative authorization DSL itself since it would need to be parsed first, creating a kind of circular reference.
Hope this helps anyone out there needing it.
I have the following approach in my app and it works
role :super_user do
includes :basic_user
has_permission_on :backoffice_users do
to :edit
if_attribute :role => is {"basic_user"}
end
end
精彩评论