What's the best approach to apply role-based access authorization in Active Admin?












0















If only using ActiveAdmin I know that I can do something like this to limit the access of a certain user group to a resource:



ActiveAdmin.register Resource do
menu :parent => "Super Admin Only", :if => proc { current_admin_user.super_admin? }
end


However, if I have a dynamic access/permission control form that gets updated depending on the needs of a certain user group, I need to be able to update my ActiveAdmin respectively.



I'm saving my permission data as json (key-value pair). At first, I was thinking of using ActiveAdmin::AuthorizationAdapter



class StaffAuthorization < ActiveAdmin::AuthorizationAdapter

def authorized?(action, subject = nil)
return true if resource.try(:name) == 'Dashboard'
return false if action == :destroy

retrieve_policy(action).authorized?
end

def role
user.role
end

def policy_klass
"policy/staff/#{role}".classify.constantize
rescue NameError
Policy::Staff::Default
end

def retrieve_policy(action)
policy_klass.new(user, resource, action)
end
end


For exmaple a Processing adminuser:



module Policy::Staff
class Processing < Base
def authorized?
return true if resource.try(:resource_class) == ::Borrow
return true if resource.try(:resource_class) == ::User && action == :read
return true if [ 'Reports', 'Categorize' ].include?(resource.try(:name))
false
end
end
end


I can always generate a policy file by looping through the json on save but the function looks dirty. Always on a format returning true for a certain resource or action on it.



Any better way to do this kind of feature in ActiveAdmin?



Limitations:
Running ActiveAdmin 1.0.0
Ransack 1.8.4




  • If I change/update any of the two I get painful list of errors.










share|improve this question



























    0















    If only using ActiveAdmin I know that I can do something like this to limit the access of a certain user group to a resource:



    ActiveAdmin.register Resource do
    menu :parent => "Super Admin Only", :if => proc { current_admin_user.super_admin? }
    end


    However, if I have a dynamic access/permission control form that gets updated depending on the needs of a certain user group, I need to be able to update my ActiveAdmin respectively.



    I'm saving my permission data as json (key-value pair). At first, I was thinking of using ActiveAdmin::AuthorizationAdapter



    class StaffAuthorization < ActiveAdmin::AuthorizationAdapter

    def authorized?(action, subject = nil)
    return true if resource.try(:name) == 'Dashboard'
    return false if action == :destroy

    retrieve_policy(action).authorized?
    end

    def role
    user.role
    end

    def policy_klass
    "policy/staff/#{role}".classify.constantize
    rescue NameError
    Policy::Staff::Default
    end

    def retrieve_policy(action)
    policy_klass.new(user, resource, action)
    end
    end


    For exmaple a Processing adminuser:



    module Policy::Staff
    class Processing < Base
    def authorized?
    return true if resource.try(:resource_class) == ::Borrow
    return true if resource.try(:resource_class) == ::User && action == :read
    return true if [ 'Reports', 'Categorize' ].include?(resource.try(:name))
    false
    end
    end
    end


    I can always generate a policy file by looping through the json on save but the function looks dirty. Always on a format returning true for a certain resource or action on it.



    Any better way to do this kind of feature in ActiveAdmin?



    Limitations:
    Running ActiveAdmin 1.0.0
    Ransack 1.8.4




    • If I change/update any of the two I get painful list of errors.










    share|improve this question

























      0












      0








      0








      If only using ActiveAdmin I know that I can do something like this to limit the access of a certain user group to a resource:



      ActiveAdmin.register Resource do
      menu :parent => "Super Admin Only", :if => proc { current_admin_user.super_admin? }
      end


      However, if I have a dynamic access/permission control form that gets updated depending on the needs of a certain user group, I need to be able to update my ActiveAdmin respectively.



      I'm saving my permission data as json (key-value pair). At first, I was thinking of using ActiveAdmin::AuthorizationAdapter



      class StaffAuthorization < ActiveAdmin::AuthorizationAdapter

      def authorized?(action, subject = nil)
      return true if resource.try(:name) == 'Dashboard'
      return false if action == :destroy

      retrieve_policy(action).authorized?
      end

      def role
      user.role
      end

      def policy_klass
      "policy/staff/#{role}".classify.constantize
      rescue NameError
      Policy::Staff::Default
      end

      def retrieve_policy(action)
      policy_klass.new(user, resource, action)
      end
      end


      For exmaple a Processing adminuser:



      module Policy::Staff
      class Processing < Base
      def authorized?
      return true if resource.try(:resource_class) == ::Borrow
      return true if resource.try(:resource_class) == ::User && action == :read
      return true if [ 'Reports', 'Categorize' ].include?(resource.try(:name))
      false
      end
      end
      end


      I can always generate a policy file by looping through the json on save but the function looks dirty. Always on a format returning true for a certain resource or action on it.



      Any better way to do this kind of feature in ActiveAdmin?



      Limitations:
      Running ActiveAdmin 1.0.0
      Ransack 1.8.4




      • If I change/update any of the two I get painful list of errors.










      share|improve this question














      If only using ActiveAdmin I know that I can do something like this to limit the access of a certain user group to a resource:



      ActiveAdmin.register Resource do
      menu :parent => "Super Admin Only", :if => proc { current_admin_user.super_admin? }
      end


      However, if I have a dynamic access/permission control form that gets updated depending on the needs of a certain user group, I need to be able to update my ActiveAdmin respectively.



      I'm saving my permission data as json (key-value pair). At first, I was thinking of using ActiveAdmin::AuthorizationAdapter



      class StaffAuthorization < ActiveAdmin::AuthorizationAdapter

      def authorized?(action, subject = nil)
      return true if resource.try(:name) == 'Dashboard'
      return false if action == :destroy

      retrieve_policy(action).authorized?
      end

      def role
      user.role
      end

      def policy_klass
      "policy/staff/#{role}".classify.constantize
      rescue NameError
      Policy::Staff::Default
      end

      def retrieve_policy(action)
      policy_klass.new(user, resource, action)
      end
      end


      For exmaple a Processing adminuser:



      module Policy::Staff
      class Processing < Base
      def authorized?
      return true if resource.try(:resource_class) == ::Borrow
      return true if resource.try(:resource_class) == ::User && action == :read
      return true if [ 'Reports', 'Categorize' ].include?(resource.try(:name))
      false
      end
      end
      end


      I can always generate a policy file by looping through the json on save but the function looks dirty. Always on a format returning true for a certain resource or action on it.



      Any better way to do this kind of feature in ActiveAdmin?



      Limitations:
      Running ActiveAdmin 1.0.0
      Ransack 1.8.4




      • If I change/update any of the two I get painful list of errors.







      ruby ruby-on-rails-4 activeadmin






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 '18 at 9:13









      TheresaTheresa

      159




      159
























          1 Answer
          1






          active

          oldest

          votes


















          0














          I recommend the cancan adapter, which appears to be available in ActiveAdmin 1.0.0.



          First, install cancancan (the successor to cancan) by adding it to your Gemfile. Then set up the adapter:



          config.authorization_adapter = ActiveAdmin::CanCanAdapter


          Then define an app/models/ability.rb class.



          I have something like this (borrowing from your example and extending it a little):



          class Ability
          include CanCan::Ability

          def initialize(user)
          can :read, ActiveAdmin::Page, name: 'Dashboard'

          case user.role
          when 'superuser'
          # superusers can do everything, no need to specify
          can :manage, :all
          when 'processing'
          basic(user)
          processing(user)
          when 'another-role'
          basic(user)
          end
          end


          private

          def basic(user)
          # The user can read all users
          can :read, User

          # and they can manage themselves
          can :manage, user
          end

          def processing(user)
          can :manage, Borrow

          # The conditions hash allows cancan to generate a query
          # to load accessible records as well as check individual
          # records.
          can :manage, OtherThing, name: ['Reports', 'Categorize']
          end
          end


          I've had good luck with cancancan, for fairly complex authorization, but I haven't tried the other built-in adapter: pundit, so I don't know how it compares.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53334682%2fwhats-the-best-approach-to-apply-role-based-access-authorization-in-active-admi%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            I recommend the cancan adapter, which appears to be available in ActiveAdmin 1.0.0.



            First, install cancancan (the successor to cancan) by adding it to your Gemfile. Then set up the adapter:



            config.authorization_adapter = ActiveAdmin::CanCanAdapter


            Then define an app/models/ability.rb class.



            I have something like this (borrowing from your example and extending it a little):



            class Ability
            include CanCan::Ability

            def initialize(user)
            can :read, ActiveAdmin::Page, name: 'Dashboard'

            case user.role
            when 'superuser'
            # superusers can do everything, no need to specify
            can :manage, :all
            when 'processing'
            basic(user)
            processing(user)
            when 'another-role'
            basic(user)
            end
            end


            private

            def basic(user)
            # The user can read all users
            can :read, User

            # and they can manage themselves
            can :manage, user
            end

            def processing(user)
            can :manage, Borrow

            # The conditions hash allows cancan to generate a query
            # to load accessible records as well as check individual
            # records.
            can :manage, OtherThing, name: ['Reports', 'Categorize']
            end
            end


            I've had good luck with cancancan, for fairly complex authorization, but I haven't tried the other built-in adapter: pundit, so I don't know how it compares.






            share|improve this answer




























              0














              I recommend the cancan adapter, which appears to be available in ActiveAdmin 1.0.0.



              First, install cancancan (the successor to cancan) by adding it to your Gemfile. Then set up the adapter:



              config.authorization_adapter = ActiveAdmin::CanCanAdapter


              Then define an app/models/ability.rb class.



              I have something like this (borrowing from your example and extending it a little):



              class Ability
              include CanCan::Ability

              def initialize(user)
              can :read, ActiveAdmin::Page, name: 'Dashboard'

              case user.role
              when 'superuser'
              # superusers can do everything, no need to specify
              can :manage, :all
              when 'processing'
              basic(user)
              processing(user)
              when 'another-role'
              basic(user)
              end
              end


              private

              def basic(user)
              # The user can read all users
              can :read, User

              # and they can manage themselves
              can :manage, user
              end

              def processing(user)
              can :manage, Borrow

              # The conditions hash allows cancan to generate a query
              # to load accessible records as well as check individual
              # records.
              can :manage, OtherThing, name: ['Reports', 'Categorize']
              end
              end


              I've had good luck with cancancan, for fairly complex authorization, but I haven't tried the other built-in adapter: pundit, so I don't know how it compares.






              share|improve this answer


























                0












                0








                0







                I recommend the cancan adapter, which appears to be available in ActiveAdmin 1.0.0.



                First, install cancancan (the successor to cancan) by adding it to your Gemfile. Then set up the adapter:



                config.authorization_adapter = ActiveAdmin::CanCanAdapter


                Then define an app/models/ability.rb class.



                I have something like this (borrowing from your example and extending it a little):



                class Ability
                include CanCan::Ability

                def initialize(user)
                can :read, ActiveAdmin::Page, name: 'Dashboard'

                case user.role
                when 'superuser'
                # superusers can do everything, no need to specify
                can :manage, :all
                when 'processing'
                basic(user)
                processing(user)
                when 'another-role'
                basic(user)
                end
                end


                private

                def basic(user)
                # The user can read all users
                can :read, User

                # and they can manage themselves
                can :manage, user
                end

                def processing(user)
                can :manage, Borrow

                # The conditions hash allows cancan to generate a query
                # to load accessible records as well as check individual
                # records.
                can :manage, OtherThing, name: ['Reports', 'Categorize']
                end
                end


                I've had good luck with cancancan, for fairly complex authorization, but I haven't tried the other built-in adapter: pundit, so I don't know how it compares.






                share|improve this answer













                I recommend the cancan adapter, which appears to be available in ActiveAdmin 1.0.0.



                First, install cancancan (the successor to cancan) by adding it to your Gemfile. Then set up the adapter:



                config.authorization_adapter = ActiveAdmin::CanCanAdapter


                Then define an app/models/ability.rb class.



                I have something like this (borrowing from your example and extending it a little):



                class Ability
                include CanCan::Ability

                def initialize(user)
                can :read, ActiveAdmin::Page, name: 'Dashboard'

                case user.role
                when 'superuser'
                # superusers can do everything, no need to specify
                can :manage, :all
                when 'processing'
                basic(user)
                processing(user)
                when 'another-role'
                basic(user)
                end
                end


                private

                def basic(user)
                # The user can read all users
                can :read, User

                # and they can manage themselves
                can :manage, user
                end

                def processing(user)
                can :manage, Borrow

                # The conditions hash allows cancan to generate a query
                # to load accessible records as well as check individual
                # records.
                can :manage, OtherThing, name: ['Reports', 'Categorize']
                end
                end


                I've had good luck with cancancan, for fairly complex authorization, but I haven't tried the other built-in adapter: pundit, so I don't know how it compares.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 14 '18 at 0:25









                Amiel MartinAmiel Martin

                3,74912427




                3,74912427






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53334682%2fwhats-the-best-approach-to-apply-role-based-access-authorization-in-active-admi%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Xamarin.form Move up view when keyboard appear

                    Post-Redirect-Get with Spring WebFlux and Thymeleaf

                    Anylogic : not able to use stopDelay()