Module: Authorization::Controller::Runtime

Defined in:
lib/declarative_authorization/controller/runtime.rb

Constant Summary collapse

DEFAULT_DENY =
false
@@failed_auto_loading_is_not_found =

If attribute_check is set for filter_access_to, decl_auth_context will try to load the appropriate object from the current controller’s model with the id from params. If that fails, a 404 Not Found is often the right way to handle the error. If you have additional measures in place that restricts the find scope, handling this error as a permission denied might be a better way. Set failed_auto_loading_is_not_found to false for the latter behavior.

true

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.failed_auto_loading_is_not_found=(new_value) ⇒ Object



18
19
20
# File 'lib/declarative_authorization/controller/runtime.rb', line 18

def self.failed_auto_loading_is_not_found=(new_value)
  @@failed_auto_loading_is_not_found = new_value
end

.failed_auto_loading_is_not_found?Boolean

Returns:

  • (Boolean)


14
15
16
# File 'lib/declarative_authorization/controller/runtime.rb', line 14

def self.failed_auto_loading_is_not_found?
  @@failed_auto_loading_is_not_found
end

Instance Method Details

#allowed?(action_name) ⇒ Boolean

Returns:

  • (Boolean)


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/declarative_authorization/controller/runtime.rb', line 143

def allowed?(action_name)
  permissions = api_class.all_filter_access_permissions
  all_permissions = permissions.select { |p| p.actions.include?(:all) }
  matching_permissions = permissions.select { |p| p.matches?(action_name) }

  allowed = false
  auth_exception = nil

  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
  rescue ::Authorization::NotAuthorized => e
    auth_exception = e
  end

  unless allowed
    if all_permissions.empty? && matching_permissions.empty?
      logger.warn "Permission denied: No matching filter access rule found for #{api_class.name}.#{action_name}"
    elsif auth_exception
      logger.info "Permission denied: #{auth_exception}"
    end
  end

  allowed
end

#authorization_engineObject

Returns the Authorization::Engine for the current controller.



23
24
25
# File 'lib/declarative_authorization/controller/runtime.rb', line 23

def authorization_engine
  @authorization_engine ||= Authorization::Engine.instance
end

#decl_auth_contextObject



174
175
176
# File 'lib/declarative_authorization/controller/runtime.rb', line 174

def decl_auth_context
  api_class.decl_auth_context
end

#has_any_role?(*roles) ⇒ Boolean

Intended to be used where you want to allow users with any single listed role to view the content in question

Returns:

  • (Boolean)


94
95
96
97
98
99
100
101
# File 'lib/declarative_authorization/controller/runtime.rb', line 94

def has_any_role?(*roles)
  user_roles = authorization_engine.roles_for(current_user)
  result = roles.any? do |role|
    user_roles.include?(role)
  end
  yield if result && block_given?
  result
end

#has_any_role_with_hierarchy?(*roles) ⇒ Boolean

As has_any_role? except checks all roles included in the role hierarchy

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
# File 'lib/declarative_authorization/controller/runtime.rb', line 114

def has_any_role_with_hierarchy?(*roles)
  user_roles = authorization_engine.roles_with_hierarchy_for(current_user)
  result = roles.any? do |role|
    user_roles.include?(role)
  end
  yield if result && block_given?
  result
end

#has_role?(*roles) ⇒ Boolean

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 %>

Returns:

  • (Boolean)


83
84
85
86
87
88
89
90
# File 'lib/declarative_authorization/controller/runtime.rb', line 83

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 && block_given?
  result
end

#has_role_with_hierarchy?(*roles) ⇒ Boolean

As has_role? except checks all roles included in the role hierarchy

Returns:

  • (Boolean)


104
105
106
107
108
109
110
111
# File 'lib/declarative_authorization/controller/runtime.rb', line 104

def has_role_with_hierarchy?(*roles)
  user_roles = authorization_engine.roles_with_hierarchy_for(current_user)
  result = roles.all? do |role|
    user_roles.include?(role)
  end
  yield if result && block_given?
  result
end

#options_for_permit(object_or_sym = nil, options = {}, bang = true) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/declarative_authorization/controller/runtime.rb', line 123

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) && 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[:user] = current_user unless result.key?(:user)
  result
end

#permitted_to!(privilege, object_or_sym = nil, options = {}) ⇒ Object

Works similar to the permitted_to? method, but throws the authorization exceptions, just like Engine#permit!



64
65
66
# File 'lib/declarative_authorization/controller/runtime.rb', line 64

def permitted_to!(privilege, object_or_sym = nil, options = {})
  authorization_engine.permit!(privilege, options_for_permit(object_or_sym, options, true))
end

#permitted_to?(privilege, object_or_sym = nil, options = {}) ⇒ Boolean

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.

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

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
# File 'lib/declarative_authorization/controller/runtime.rb', line 53

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?
    true
  else
    false
  end
end