简体   繁体   中英

declarative_authorization permissions on roles

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.

  1. If I comment the rule out, nobody can edit
  2. If I leave the rule 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM