lib/active_admin/authorization_adapter.rb
# frozen_string_literal: true
module ActiveAdmin
# Default Authorization permissions for Active Admin
module Authorization
READ = :read
NEW = :new
CREATE = :create
EDIT = :edit
UPDATE = :update
DESTROY = :destroy
end
Auth = Authorization
# Active Admin's default authorization adapter. This adapter returns true
# for all requests to `#authorized?`. It should be the starting point for
# implementing your own authorization adapter.
#
# To view an example subclass, check out `ActiveAdmin::CanCanAdapter`
class AuthorizationAdapter
attr_reader :resource, :user
# Initialize a new authorization adapter. This happens on each and
# every request to a controller.
#
# @param [ActiveAdmin::Resource, ActiveAdmin::Page] resource The resource
# that the user is currently on. Note, we may be authorizing access
# to a different subject, so don't rely on this other than to
# pull configuration information from.
#
# @param [any] user The current user. The user is set to whatever is returned
# from `#current_active_admin_user` in the controller.
#
def initialize(resource, user)
@resource = resource
@user = user
end
# Returns true of false depending on if the user is authorized to perform
# the action on the subject.
#
# @param [Symbol] action The name of the action to perform. Usually this will be
# one of the `ActiveAdmin::Auth::*` symbols.
#
# @param [any] subject The subject the action is being performed on usually this
# is a model object. Note, that this is NOT always in instance, it can be
# the class of the subject also. For example, Active Admin uses the class
# of the resource to decide if the resource should be displayed in the
# global navigation. To deal with this nicely in a case statement, take
# a look at `#normalized(klass)`
#
# @return [Boolean]
def authorized?(action, subject = nil)
true
end
# A hook method for authorization libraries to scope the collection. By
# default, we just return the same collection. The returned scope is used
# as the starting point for all queries to the db in the controller.
#
# @param [ActiveRecord::Relation] collection The collection the user is
# attempting to view.
#
# @param [Symbol] action The name of the action to perform. Usually this will be
# one of the `ActiveAdmin::Auth::*` symbols. Defaults to `Auth::READ` if
# no action passed in.
#
# @return [ActiveRecord::Relation] A new collection, scoped to the
# objects that the current user has access to.
def scope_collection(collection, action = Auth::READ)
collection
end
private
# The `#authorized?` method's subject can be set to both instances as well
# as classes of objects. This can make it much difficult to create simple
# case statements for authorization since you have to handle both the
# class level match and the instance level match.
#
# For example:
#
# class MyAuthAdapter < ActiveAdmin::AuthorizationAdapter
#
# def authorized?(action, subject = nil)
# case subject
# when Post
# true
# when Class
# if subject == Post
# true
# end
# end
# end
#
# end
#
# To handle this, the normalized method takes care of returning a object
# which implements `===` to be matched in a case statement.
#
# The above now becomes:
#
# class MyAuthAdapter < ActiveAdmin::AuthorizationAdapter
#
# def authorized?(action, subject = nil)
# case subject
# when normalized(Post)
# true
# end
# end
#
# end
def normalized(klass)
NormalizedMatcher.new(klass)
end
class NormalizedMatcher
def initialize(klass)
@klass = klass
end
def ===(other)
@klass == other || other.is_a?(@klass)
end
end
end
end