Search code examples
ruby-on-railssecuritypermissionsnesteddeclarative-authorization

multiple conditions to user in declarative_authorization if_attribute


I have 4 different levels of access; admin, partner, employee and client. Admin, Partner, and Employee have administrative access over clients. Basically what I have done is created a Rails app where clients can upload documents to their vendor (partners). Everything works great except for the client level access. I have two codes; partercode and client code. Partners can only see files where the file's partercode field equals the partner's partner code. This works just fine. However, the client can only see files where the partnercode matches and the clientcode matches. Below is my client section. What is working is that the client IS only allowed to see the partercode files, but it is setting them see other clients that belong to the partner. (by typing in the number in the URL). I doubt this would ever be an issue, but it's a security hole that I would definitely want closed.

  role :client do
    has_permission_on [:users], :to => [:client, :edit, :update] do
      if_attribute :username => is { user.username }
    end
     has_permission_on [:documents], :to => [:client, :new, :create]
     has_permission_on [:documents], :to => [:client, :index, :show, :edit, :update, :destroy, :documents] do
       if_attribute :partnercode => is { user.partnercode }, :clientcode => is { user.clientcode }
     end
  end

Solution

  • I found the answer. The answer, ironically, was in the tags of this question; nested.

      role :client do
        has_permission_on [:users], :to => [:client, :edit, :update] do
          if_attribute :username => is { user.username }
        end
         has_permission_on [:documents], :to => [:client, :new, :create]
         has_permission_on [:documents], :to => [:client, :index, :show, :edit, :update, :destroy, :documents] do
           if_attribute :clientcode => is { user.clientcode } do
            if_attribute :partnercode => is { user.partnercode }
           end
         end
      end
    

    Once I validate that the clientcode is correct then create another do .. end to check the partnercode.