Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 48 additions & 18 deletions lib/declarative_authorization/controller/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Runtime
def self.failed_auto_loading_is_not_found?
@@failed_auto_loading_is_not_found
end

def self.failed_auto_loading_is_not_found=(new_value)
@@failed_auto_loading_is_not_found = new_value
end
Expand All @@ -28,11 +29,27 @@ def authorization_engine
# in the authorization rules are only evaluated if an object is given
# for context.
#
# See examples for Authorization::AuthorizationHelper #permitted_to?
#
# If no object or context is specified, the controller_name is used as
# context.
#
# Examples:
# <% permitted_to? :create, :users do %>
# <%= link_to 'New', new_user_path %>
# <% end %>
# ...
# <% if permitted_to? :create, :users %>
# <%= link_to 'New', new_user_path %>
# <% else %>
# You are not allowed to create new users!
# <% end %>
# ...
# <% for user in @users %>
# <%= link_to 'Edit', edit_user_path(user) if permitted_to? :update, user %>
# <% end %>
#
# To pass in an object and override the context, you can use the optional
# options:
# permitted_to? :update, user, :context => :account
def permitted_to?(privilege, object_or_sym = nil, options = {})
if authorization_engine.permit!(privilege, options_for_permit(object_or_sym, options, false))
yield if block_given?
Expand All @@ -48,16 +65,27 @@ def permitted_to!(privilege, object_or_sym = nil, options = {})
authorization_engine.permit!(privilege, options_for_permit(object_or_sym, options, true))
end

# While permitted_to? is used for authorization, in some cases
# While permitted_to? is used for authorization in views, in some cases
# content should only be shown to some users without being concerned
# with authorization. E.g. to only show the most relevant menu options
# to a certain group of users. That is what has_role? should be used for.
#
# Examples:
# <% has_role?(:sales) do %>
# <%= link_to 'All contacts', contacts_path %>
# <% end %>
# ...
# <% if has_role?(:sales) %>
# <%= link_to 'Customer contacts', contacts_path %>
# <% else %>
# ...
# <% end %>
def has_role?(*roles)
user_roles = authorization_engine.roles_for(current_user)
result = roles.all? do |role|
user_roles.include?(role)
end
yield if result and block_given?
yield if result && block_given?
result
end

Expand All @@ -68,7 +96,7 @@ def has_any_role?(*roles)
result = roles.any? do |role|
user_roles.include?(role)
end
yield if result and block_given?
yield if result && block_given?
result
end

Expand All @@ -78,7 +106,7 @@ def has_role_with_hierarchy?(*roles)
result = roles.all? do |role|
user_roles.include?(role)
end
yield if result and block_given?
yield if result && block_given?
result
end

Expand All @@ -88,24 +116,26 @@ def has_any_role_with_hierarchy?(*roles)
result = roles.any? do |role|
user_roles.include?(role)
end
yield if result and block_given?
yield if result && block_given?
result
end

def options_for_permit(object_or_sym = nil, options = {}, bang = true)
context = object = nil
if object_or_sym.nil?
context = decl_auth_context
elsif !Authorization.is_a_association_proxy?(object_or_sym) and object_or_sym.is_a?(Symbol)
elsif !Authorization.is_a_association_proxy?(object_or_sym) && object_or_sym.is_a?(Symbol)
context = object_or_sym
else
object = object_or_sym
end

result = {:object => object,
:context => context,
:skip_attribute_test => object.nil?,
:bang => bang}.merge(options)
result = {
object: object,
context: context,
skip_attribute_test: object.nil?,
bang: bang
}.merge(options)
result[:user] = current_user unless result.key?(:user)
result
end
Expand All @@ -120,12 +150,12 @@ def allowed?(action_name)

begin
allowed = if matching_permissions.any?
matching_permissions.all? { |p| p.permit!(self, action_name) }
elsif all_permissions.any?
all_permissions.all? { |p| p.permit!(self, action_name) }
else
!DEFAULT_DENY
end
matching_permissions.all? { |p| p.permit!(self, action_name) }
elsif all_permissions.any?
all_permissions.all? { |p| p.permit!(self, action_name) }
else
!DEFAULT_DENY
end
rescue ::Authorization::NotAuthorized => e
auth_exception = e
end
Expand Down
78 changes: 6 additions & 72 deletions lib/declarative_authorization/helper.rb
Original file line number Diff line number Diff line change
@@ -1,78 +1,12 @@
# Authorization::AuthorizationHelper
require File.dirname(__FILE__) + '/authorization.rb'
require "#{File.dirname(__FILE__)}/authorization.rb"

module Authorization
# Include this module in your views
module AuthorizationHelper

# If the current user meets the given privilege, permitted_to? returns true
# and yields to the optional block. The attribute checks that are defined
# in the authorization rules are only evaluated if an object is given
# for context.
#
# Examples:
# <% permitted_to? :create, :users do %>
# <%= link_to 'New', new_user_path %>
# <% end %>
# ...
# <% if permitted_to? :create, :users %>
# <%= link_to 'New', new_user_path %>
# <% else %>
# You are not allowed to create new users!
# <% end %>
# ...
# <% for user in @users %>
# <%= link_to 'Edit', edit_user_path(user) if permitted_to? :update, user %>
# <% end %>
#
# To pass in an object and override the context, you can use the optional
# options:
# permitted_to? :update, user, :context => :account
#
def permitted_to?(privilege, object_or_sym = nil, options = {})
controller.permitted_to?(privilege, object_or_sym, options) do
yield if block_given?
end
end

# While permitted_to? is used for authorization in views, in some cases
# content should only be shown to some users without being concerned
# with authorization. E.g. to only show the most relevant menu options
# to a certain group of users. That is what has_role? should be used for.
#
# Examples:
# <% has_role?(:sales) do %>
# <%= link_to 'All contacts', contacts_path %>
# <% end %>
# ...
# <% if has_role?(:sales) %>
# <%= link_to 'Customer contacts', contacts_path %>
# <% else %>
# ...
# <% end %>
#
def has_role?(*roles)
controller.has_role?(*roles) do
yield if block_given?
end
end

# As has_role? except checks all roles included in the role hierarchy
def has_role_with_hierarchy?(*roles)
controller.has_role_with_hierarchy?(*roles) do
yield if block_given?
end
end

def has_any_role?(*roles)
controller.has_any_role?(*roles) do
yield if block_given?
end
end

def has_any_role_with_hierarchy?(*roles)
controller.has_any_role_with_hierarchy?(*roles) do
yield if block_given?
end
end
delegate :has_role?, :has_role_with_hierarchy?,
:has_any_role?, :has_any_role_with_hierarchy?,
:permitted_to?,
to: :controller
end
end
Loading