What's the best approach to apply role-based access authorization in Active Admin?
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
add a comment |
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
add a comment |
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
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
ruby ruby-on-rails-4 activeadmin
asked Nov 16 '18 at 9:13
TheresaTheresa
159
159
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
answered Dec 14 '18 at 0:25
Amiel MartinAmiel Martin
3,74912427
3,74912427
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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