mirror of
				https://github.com/varvet/pundit.git
				synced 2022-11-09 12:30:11 -05:00 
			
		
		
		
	Extract Pundit controller authorization module
This commit is contained in:
		
							parent
							
								
									46af6620b0
								
							
						
					
					
						commit
						4d9b5849f4
					
				
					 7 changed files with 454 additions and 414 deletions
				
			
		| 
						 | 
				
			
			@ -30,6 +30,10 @@ changes.
 | 
			
		|||
- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 (#676)
 | 
			
		||||
- Dropped support for RSpec 2 (#615)
 | 
			
		||||
 | 
			
		||||
### Deprecated
 | 
			
		||||
 | 
			
		||||
- Deprecate `include Pundit` in favor of `include Pundit::Authorization` (#621)
 | 
			
		||||
 | 
			
		||||
## 2.1.0 (2019-08-14)
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -26,11 +26,11 @@ Sponsored by:
 | 
			
		|||
gem "pundit"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Include Pundit in your application controller:
 | 
			
		||||
Include `Pundit::Authorization` in your application controller:
 | 
			
		||||
 | 
			
		||||
``` ruby
 | 
			
		||||
class ApplicationController < ActionController::Base
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +334,7 @@ that you haven't forgotten to authorize the action. For example:
 | 
			
		|||
 | 
			
		||||
``` ruby
 | 
			
		||||
class ApplicationController < ActionController::Base
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
  after_action :verify_authorized
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +347,7 @@ authorize individual instances.
 | 
			
		|||
 | 
			
		||||
``` ruby
 | 
			
		||||
class ApplicationController < ActionController::Base
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
  after_action :verify_authorized, except: :index
 | 
			
		||||
  after_action :verify_policy_scoped, only: :index
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -490,7 +490,7 @@ method in every controller.
 | 
			
		|||
 | 
			
		||||
```ruby
 | 
			
		||||
class ApplicationController < ActionController::Base
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
 | 
			
		||||
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +643,7 @@ class UserContext
 | 
			
		|||
end
 | 
			
		||||
 | 
			
		||||
class ApplicationController
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
 | 
			
		||||
  def pundit_user
 | 
			
		||||
    UserContext.new(current_user, request.ip)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										167
									
								
								lib/pundit.rb
									
										
									
									
									
								
							
							
						
						
									
										167
									
								
								lib/pundit.rb
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@ require "active_support/core_ext/string/inflections"
 | 
			
		|||
require "active_support/core_ext/object/blank"
 | 
			
		||||
require "active_support/core_ext/module/introspection"
 | 
			
		||||
require "active_support/dependencies/autoload"
 | 
			
		||||
require "pundit/authorization"
 | 
			
		||||
 | 
			
		||||
# @api private
 | 
			
		||||
# To avoid name clashes with common Error naming when mixing in Pundit,
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +54,10 @@ module Pundit
 | 
			
		|||
  # Error that will be raised if a policy or policy scope is not defined.
 | 
			
		||||
  class NotDefinedError < Error; end
 | 
			
		||||
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
  def self.included(base)
 | 
			
		||||
    warn "[DEPRECATION] 'include Pundit' is deprecated. Please use 'include Pundit::Authorization' instead."
 | 
			
		||||
    base.include Authorization
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    # Retrieves the policy for the given record, initializing it with the
 | 
			
		||||
| 
						 | 
				
			
			@ -163,165 +167,4 @@ module Pundit
 | 
			
		|||
      pundit_policy_scope(scope)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  included do
 | 
			
		||||
    helper Helper if respond_to?(:helper)
 | 
			
		||||
    if respond_to?(:helper_method)
 | 
			
		||||
      helper_method :policy
 | 
			
		||||
      helper_method :pundit_policy_scope
 | 
			
		||||
      helper_method :pundit_user
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  # @return [Boolean] whether authorization has been performed, i.e. whether
 | 
			
		||||
  #                   one {#authorize} or {#skip_authorization} has been called
 | 
			
		||||
  def pundit_policy_authorized?
 | 
			
		||||
    !!@_pundit_policy_authorized
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # @return [Boolean] whether policy scoping has been performed, i.e. whether
 | 
			
		||||
  #                   one {#policy_scope} or {#skip_policy_scope} has been called
 | 
			
		||||
  def pundit_policy_scoped?
 | 
			
		||||
    !!@_pundit_policy_scoped
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Raises an error if authorization has not been performed, usually used as an
 | 
			
		||||
  # `after_action` filter to prevent programmer error in forgetting to call
 | 
			
		||||
  # {#authorize} or {#skip_authorization}.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
  # @raise [AuthorizationNotPerformedError] if authorization has not been performed
 | 
			
		||||
  # @return [void]
 | 
			
		||||
  def verify_authorized
 | 
			
		||||
    raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Raises an error if policy scoping has not been performed, usually used as an
 | 
			
		||||
  # `after_action` filter to prevent programmer error in forgetting to call
 | 
			
		||||
  # {#policy_scope} or {#skip_policy_scope} in index actions.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
  # @raise [AuthorizationNotPerformedError] if policy scoping has not been performed
 | 
			
		||||
  # @return [void]
 | 
			
		||||
  def verify_policy_scoped
 | 
			
		||||
    raise PolicyScopingNotPerformedError, self.class unless pundit_policy_scoped?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Retrieves the policy for the given record, initializing it with the record
 | 
			
		||||
  # and current user and finally throwing an error if the user is not
 | 
			
		||||
  # authorized to perform the given action.
 | 
			
		||||
  #
 | 
			
		||||
  # @param record [Object, Array] the object we're checking permissions of
 | 
			
		||||
  # @param query [Symbol, String] the predicate method to check on the policy (e.g. `:show?`).
 | 
			
		||||
  #   If omitted then this defaults to the Rails controller action name.
 | 
			
		||||
  # @param policy_class [Class] the policy class we want to force use of
 | 
			
		||||
  # @raise [NotAuthorizedError] if the given query method returned false
 | 
			
		||||
  # @return [Object] Always returns the passed object record
 | 
			
		||||
  def authorize(record, query = nil, policy_class: nil)
 | 
			
		||||
    query ||= "#{action_name}?"
 | 
			
		||||
 | 
			
		||||
    @_pundit_policy_authorized = true
 | 
			
		||||
 | 
			
		||||
    Pundit.authorize(pundit_user, record, query, policy_class: policy_class, cache: policies)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Allow this action not to perform authorization.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
  # @return [void]
 | 
			
		||||
  def skip_authorization
 | 
			
		||||
    @_pundit_policy_authorized = :skipped
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Allow this action not to perform policy scoping.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
  # @return [void]
 | 
			
		||||
  def skip_policy_scope
 | 
			
		||||
    @_pundit_policy_scoped = :skipped
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Retrieves the policy scope for the given record.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#scopes
 | 
			
		||||
  # @param scope [Object] the object we're retrieving the policy scope for
 | 
			
		||||
  # @param policy_scope_class [Class] the policy scope class we want to force use of
 | 
			
		||||
  # @return [Scope{#resolve}, nil] instance of scope class which can resolve to a scope
 | 
			
		||||
  def policy_scope(scope, policy_scope_class: nil)
 | 
			
		||||
    @_pundit_policy_scoped = true
 | 
			
		||||
    policy_scope_class ? policy_scope_class.new(pundit_user, scope).resolve : pundit_policy_scope(scope)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Retrieves the policy for the given record.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#policies
 | 
			
		||||
  # @param record [Object] the object we're retrieving the policy for
 | 
			
		||||
  # @return [Object, nil] instance of policy class with query methods
 | 
			
		||||
  def policy(record)
 | 
			
		||||
    policies[record] ||= Pundit.policy!(pundit_user, record)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Retrieves a set of permitted attributes from the policy by instantiating
 | 
			
		||||
  # the policy class for the given record and calling `permitted_attributes` on
 | 
			
		||||
  # it, or `permitted_attributes_for_{action}` if `action` is defined. It then infers
 | 
			
		||||
  # what key the record should have in the params hash and retrieves the
 | 
			
		||||
  # permitted attributes from the params hash under that key.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#strong-parameters
 | 
			
		||||
  # @param record [Object] the object we're retrieving permitted attributes for
 | 
			
		||||
  # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`).
 | 
			
		||||
  #   If omitted then this defaults to the Rails controller action name.
 | 
			
		||||
  # @return [Hash{String => Object}] the permitted attributes
 | 
			
		||||
  def permitted_attributes(record, action = action_name)
 | 
			
		||||
    policy = policy(record)
 | 
			
		||||
    method_name = if policy.respond_to?("permitted_attributes_for_#{action}")
 | 
			
		||||
      "permitted_attributes_for_#{action}"
 | 
			
		||||
    else
 | 
			
		||||
      "permitted_attributes"
 | 
			
		||||
    end
 | 
			
		||||
    pundit_params_for(record).permit(*policy.public_send(method_name))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Retrieves the params for the given record.
 | 
			
		||||
  #
 | 
			
		||||
  # @param record [Object] the object we're retrieving params for
 | 
			
		||||
  # @return [ActionController::Parameters] the params
 | 
			
		||||
  def pundit_params_for(record)
 | 
			
		||||
    params.require(PolicyFinder.new(record).param_key)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Cache of policies. You should not rely on this method.
 | 
			
		||||
  #
 | 
			
		||||
  # @api private
 | 
			
		||||
  # rubocop:disable Naming/MemoizedInstanceVariableName
 | 
			
		||||
  def policies
 | 
			
		||||
    @_pundit_policies ||= {}
 | 
			
		||||
  end
 | 
			
		||||
  # rubocop:enable Naming/MemoizedInstanceVariableName
 | 
			
		||||
 | 
			
		||||
  # Cache of policy scope. You should not rely on this method.
 | 
			
		||||
  #
 | 
			
		||||
  # @api private
 | 
			
		||||
  # rubocop:disable Naming/MemoizedInstanceVariableName
 | 
			
		||||
  def policy_scopes
 | 
			
		||||
    @_pundit_policy_scopes ||= {}
 | 
			
		||||
  end
 | 
			
		||||
  # rubocop:enable Naming/MemoizedInstanceVariableName
 | 
			
		||||
 | 
			
		||||
  # Hook method which allows customizing which user is passed to policies and
 | 
			
		||||
  # scopes initialized by {#authorize}, {#policy} and {#policy_scope}.
 | 
			
		||||
  #
 | 
			
		||||
  # @see https://github.com/varvet/pundit#customize-pundit-user
 | 
			
		||||
  # @return [Object] the user object to be used with pundit
 | 
			
		||||
  def pundit_user
 | 
			
		||||
    current_user
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def pundit_policy_scope(scope)
 | 
			
		||||
    policy_scopes[scope] ||= Pundit.policy_scope!(pundit_user, scope)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										168
									
								
								lib/pundit/authorization.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								lib/pundit/authorization.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,168 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Pundit
 | 
			
		||||
  module Authorization
 | 
			
		||||
    extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
    included do
 | 
			
		||||
      helper Helper if respond_to?(:helper)
 | 
			
		||||
      if respond_to?(:helper_method)
 | 
			
		||||
        helper_method :policy
 | 
			
		||||
        helper_method :pundit_policy_scope
 | 
			
		||||
        helper_method :pundit_user
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    protected
 | 
			
		||||
 | 
			
		||||
    # @return [Boolean] whether authorization has been performed, i.e. whether
 | 
			
		||||
    #                   one {#authorize} or {#skip_authorization} has been called
 | 
			
		||||
    def pundit_policy_authorized?
 | 
			
		||||
      !!@_pundit_policy_authorized
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [Boolean] whether policy scoping has been performed, i.e. whether
 | 
			
		||||
    #                   one {#policy_scope} or {#skip_policy_scope} has been called
 | 
			
		||||
    def pundit_policy_scoped?
 | 
			
		||||
      !!@_pundit_policy_scoped
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Raises an error if authorization has not been performed, usually used as an
 | 
			
		||||
    # `after_action` filter to prevent programmer error in forgetting to call
 | 
			
		||||
    # {#authorize} or {#skip_authorization}.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
    # @raise [AuthorizationNotPerformedError] if authorization has not been performed
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def verify_authorized
 | 
			
		||||
      raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Raises an error if policy scoping has not been performed, usually used as an
 | 
			
		||||
    # `after_action` filter to prevent programmer error in forgetting to call
 | 
			
		||||
    # {#policy_scope} or {#skip_policy_scope} in index actions.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
    # @raise [AuthorizationNotPerformedError] if policy scoping has not been performed
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def verify_policy_scoped
 | 
			
		||||
      raise PolicyScopingNotPerformedError, self.class unless pundit_policy_scoped?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Retrieves the policy for the given record, initializing it with the record
 | 
			
		||||
    # and current user and finally throwing an error if the user is not
 | 
			
		||||
    # authorized to perform the given action.
 | 
			
		||||
    #
 | 
			
		||||
    # @param record [Object, Array] the object we're checking permissions of
 | 
			
		||||
    # @param query [Symbol, String] the predicate method to check on the policy (e.g. `:show?`).
 | 
			
		||||
    #   If omitted then this defaults to the Rails controller action name.
 | 
			
		||||
    # @param policy_class [Class] the policy class we want to force use of
 | 
			
		||||
    # @raise [NotAuthorizedError] if the given query method returned false
 | 
			
		||||
    # @return [Object] Always returns the passed object record
 | 
			
		||||
    def authorize(record, query = nil, policy_class: nil)
 | 
			
		||||
      query ||= "#{action_name}?"
 | 
			
		||||
 | 
			
		||||
      @_pundit_policy_authorized = true
 | 
			
		||||
 | 
			
		||||
      Pundit.authorize(pundit_user, record, query, policy_class: policy_class, cache: policies)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Allow this action not to perform authorization.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def skip_authorization
 | 
			
		||||
      @_pundit_policy_authorized = :skipped
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Allow this action not to perform policy scoping.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def skip_policy_scope
 | 
			
		||||
      @_pundit_policy_scoped = :skipped
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Retrieves the policy scope for the given record.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#scopes
 | 
			
		||||
    # @param scope [Object] the object we're retrieving the policy scope for
 | 
			
		||||
    # @param policy_scope_class [Class] the policy scope class we want to force use of
 | 
			
		||||
    # @return [Scope{#resolve}, nil] instance of scope class which can resolve to a scope
 | 
			
		||||
    def policy_scope(scope, policy_scope_class: nil)
 | 
			
		||||
      @_pundit_policy_scoped = true
 | 
			
		||||
      policy_scope_class ? policy_scope_class.new(pundit_user, scope).resolve : pundit_policy_scope(scope)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Retrieves the policy for the given record.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#policies
 | 
			
		||||
    # @param record [Object] the object we're retrieving the policy for
 | 
			
		||||
    # @return [Object, nil] instance of policy class with query methods
 | 
			
		||||
    def policy(record)
 | 
			
		||||
      policies[record] ||= Pundit.policy!(pundit_user, record)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Retrieves a set of permitted attributes from the policy by instantiating
 | 
			
		||||
    # the policy class for the given record and calling `permitted_attributes` on
 | 
			
		||||
    # it, or `permitted_attributes_for_{action}` if `action` is defined. It then infers
 | 
			
		||||
    # what key the record should have in the params hash and retrieves the
 | 
			
		||||
    # permitted attributes from the params hash under that key.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#strong-parameters
 | 
			
		||||
    # @param record [Object] the object we're retrieving permitted attributes for
 | 
			
		||||
    # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`).
 | 
			
		||||
    #   If omitted then this defaults to the Rails controller action name.
 | 
			
		||||
    # @return [Hash{String => Object}] the permitted attributes
 | 
			
		||||
    def permitted_attributes(record, action = action_name)
 | 
			
		||||
      policy = policy(record)
 | 
			
		||||
      method_name = if policy.respond_to?("permitted_attributes_for_#{action}")
 | 
			
		||||
        "permitted_attributes_for_#{action}"
 | 
			
		||||
      else
 | 
			
		||||
        "permitted_attributes"
 | 
			
		||||
      end
 | 
			
		||||
      pundit_params_for(record).permit(*policy.public_send(method_name))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Retrieves the params for the given record.
 | 
			
		||||
    #
 | 
			
		||||
    # @param record [Object] the object we're retrieving params for
 | 
			
		||||
    # @return [ActionController::Parameters] the params
 | 
			
		||||
    def pundit_params_for(record)
 | 
			
		||||
      params.require(PolicyFinder.new(record).param_key)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Cache of policies. You should not rely on this method.
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    # rubocop:disable Naming/MemoizedInstanceVariableName
 | 
			
		||||
    def policies
 | 
			
		||||
      @_pundit_policies ||= {}
 | 
			
		||||
    end
 | 
			
		||||
    # rubocop:enable Naming/MemoizedInstanceVariableName
 | 
			
		||||
 | 
			
		||||
    # Cache of policy scope. You should not rely on this method.
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    # rubocop:disable Naming/MemoizedInstanceVariableName
 | 
			
		||||
    def policy_scopes
 | 
			
		||||
      @_pundit_policy_scopes ||= {}
 | 
			
		||||
    end
 | 
			
		||||
    # rubocop:enable Naming/MemoizedInstanceVariableName
 | 
			
		||||
 | 
			
		||||
    # Hook method which allows customizing which user is passed to policies and
 | 
			
		||||
    # scopes initialized by {#authorize}, {#policy} and {#policy_scope}.
 | 
			
		||||
    #
 | 
			
		||||
    # @see https://github.com/varvet/pundit#customize-pundit-user
 | 
			
		||||
    # @return [Object] the user object to be used with pundit
 | 
			
		||||
    def pundit_user
 | 
			
		||||
      current_user
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def pundit_policy_scope(scope)
 | 
			
		||||
      policy_scopes[scope] ||= Pundit.policy_scope!(pundit_user, scope)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										258
									
								
								spec/authorization_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								spec/authorization_spec.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,258 @@
 | 
			
		|||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "spec_helper"
 | 
			
		||||
 | 
			
		||||
describe Pundit::Authorization do
 | 
			
		||||
  let(:controller) { Controller.new(user, "update", {}) }
 | 
			
		||||
  let(:user) { double }
 | 
			
		||||
  let(:post) { Post.new(user) }
 | 
			
		||||
  let(:customer_post) { Customer::Post.new(user) }
 | 
			
		||||
  let(:comment) { Comment.new }
 | 
			
		||||
  let(:article) { Article.new }
 | 
			
		||||
  let(:article_tag) { ArticleTag.new }
 | 
			
		||||
  let(:wiki) { Wiki.new }
 | 
			
		||||
 | 
			
		||||
  describe "#verify_authorized" do
 | 
			
		||||
    it "does nothing when authorized" do
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      controller.verify_authorized
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an exception when not authorized" do
 | 
			
		||||
      expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#verify_policy_scoped" do
 | 
			
		||||
    it "does nothing when policy_scope is used" do
 | 
			
		||||
      controller.policy_scope(Post)
 | 
			
		||||
      controller.verify_policy_scoped
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an exception when policy_scope is not used" do
 | 
			
		||||
      expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_policy_authorized?" do
 | 
			
		||||
    it "is true when authorized" do
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      expect(controller.pundit_policy_authorized?).to be true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "is false when not authorized" do
 | 
			
		||||
      expect(controller.pundit_policy_authorized?).to be false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_policy_scoped?" do
 | 
			
		||||
    it "is true when policy_scope is used" do
 | 
			
		||||
      controller.policy_scope(Post)
 | 
			
		||||
      expect(controller.pundit_policy_scoped?).to be true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "is false when policy scope is not used" do
 | 
			
		||||
      expect(controller.pundit_policy_scoped?).to be false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#authorize" do
 | 
			
		||||
    it "infers the policy name and authorizes based on it" do
 | 
			
		||||
      expect(controller.authorize(post)).to be_truthy
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record on successful authorization" do
 | 
			
		||||
      expect(controller.authorize(post)).to eq(post)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record when passed record with namespace " do
 | 
			
		||||
      expect(controller.authorize([:project, comment], :update?)).to eq(comment)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record when passed record with nested namespace " do
 | 
			
		||||
      expect(controller.authorize([:project, :admin, comment], :update?)).to eq(comment)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the policy name symbol when passed record with headless policy" do
 | 
			
		||||
      expect(controller.authorize(:publication, :create?)).to eq(:publication)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the class when passed record not a particular instance" do
 | 
			
		||||
      expect(controller.authorize(Post, :show?)).to eq(Post)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be given a different permission to check" do
 | 
			
		||||
      expect(controller.authorize(post, :show?)).to be_truthy
 | 
			
		||||
      expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be given a different policy class" do
 | 
			
		||||
      expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works with anonymous class policies" do
 | 
			
		||||
      expect(controller.authorize(article_tag, :show?)).to be_truthy
 | 
			
		||||
      expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception when the permission check fails" do
 | 
			
		||||
      expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception when a policy cannot be found" do
 | 
			
		||||
      expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "caches the policy" do
 | 
			
		||||
      expect(controller.policies[post]).to be_nil
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      expect(controller.policies[post]).not_to be_nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error when the given record is nil" do
 | 
			
		||||
      expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy constructor" do
 | 
			
		||||
      expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#skip_authorization" do
 | 
			
		||||
    it "disables authorization verification" do
 | 
			
		||||
      controller.skip_authorization
 | 
			
		||||
      expect { controller.verify_authorized }.not_to raise_error
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#skip_policy_scope" do
 | 
			
		||||
    it "disables policy scope verification" do
 | 
			
		||||
      controller.skip_policy_scope
 | 
			
		||||
      expect { controller.verify_policy_scoped }.not_to raise_error
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_user" do
 | 
			
		||||
    it "returns the same thing as current_user" do
 | 
			
		||||
      expect(controller.pundit_user).to eq controller.current_user
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#policy" do
 | 
			
		||||
    it "returns an instantiated policy" do
 | 
			
		||||
      policy = controller.policy(post)
 | 
			
		||||
      expect(policy.user).to eq user
 | 
			
		||||
      expect(policy.post).to eq post
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception if the given policy can't be found" do
 | 
			
		||||
      expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy constructor" do
 | 
			
		||||
      expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy to be injected" do
 | 
			
		||||
      new_policy = OpenStruct.new
 | 
			
		||||
      controller.policies[post] = new_policy
 | 
			
		||||
 | 
			
		||||
      expect(controller.policy(post)).to eq new_policy
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#policy_scope" do
 | 
			
		||||
    it "returns an instantiated policy scope" do
 | 
			
		||||
      expect(controller.policy_scope(Post)).to eq :published
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy scope class to be overriden" do
 | 
			
		||||
      expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception if the given policy can't be found" do
 | 
			
		||||
      expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy scope constructor" do
 | 
			
		||||
      expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy_scope to be injected" do
 | 
			
		||||
      new_scope = OpenStruct.new
 | 
			
		||||
      controller.policy_scopes[Post] = new_scope
 | 
			
		||||
 | 
			
		||||
      expect(controller.policy_scope(Post)).to eq new_scope
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#permitted_attributes" do
 | 
			
		||||
    it "checks policy for permitted attributes" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(
 | 
			
		||||
        "title" => "Hello",
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
      expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq("votes" => 5)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "checks policy for permitted attributes for record of a ActiveModel type" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        customer_post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(
 | 
			
		||||
        "title" => "Hello",
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
      expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#permitted_attributes_for_action" do
 | 
			
		||||
    it "is checked if it is defined in the policy" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          body: "blah",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "revise"
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be explicitly set" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          body: "blah",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ RSpec.describe Pundit do
 | 
			
		|||
  let(:comment) { Comment.new }
 | 
			
		||||
  let(:comment_four_five_six) { CommentFourFiveSix.new }
 | 
			
		||||
  let(:article) { Article.new }
 | 
			
		||||
  let(:controller) { Controller.new(user, "update", {}) }
 | 
			
		||||
  let(:artificial_blog) { ArtificialBlog.new }
 | 
			
		||||
  let(:article_tag) { ArticleTag.new }
 | 
			
		||||
  let(:comments_relation) { CommentsRelation.new }
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +17,6 @@ RSpec.describe Pundit do
 | 
			
		|||
  let(:tag_four_five_six) { ProjectOneTwoThree::TagFourFiveSix.new(user) }
 | 
			
		||||
  let(:avatar_four_five_six) { ProjectOneTwoThree::AvatarFourFiveSix.new }
 | 
			
		||||
  let(:wiki) { Wiki.new }
 | 
			
		||||
  let(:thread) { Thread.new }
 | 
			
		||||
 | 
			
		||||
  describe ".authorize" do
 | 
			
		||||
    it "infers the policy and authorizes based on it" do
 | 
			
		||||
| 
						 | 
				
			
			@ -397,252 +395,21 @@ RSpec.describe Pundit do
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#verify_authorized" do
 | 
			
		||||
    it "does nothing when authorized" do
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      controller.verify_authorized
 | 
			
		||||
  describe ".included" do
 | 
			
		||||
    it "includes Authorization module" do
 | 
			
		||||
      klass = Class.new
 | 
			
		||||
      klass.include Pundit
 | 
			
		||||
 | 
			
		||||
      expect(klass).to include Pundit::Authorization
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an exception when not authorized" do
 | 
			
		||||
      expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
    it "warns about deprecation" do
 | 
			
		||||
      allow(Pundit).to receive(:warn)
 | 
			
		||||
 | 
			
		||||
  describe "#verify_policy_scoped" do
 | 
			
		||||
    it "does nothing when policy_scope is used" do
 | 
			
		||||
      controller.policy_scope(Post)
 | 
			
		||||
      controller.verify_policy_scoped
 | 
			
		||||
    end
 | 
			
		||||
      klass = Class.new
 | 
			
		||||
      klass.include Pundit
 | 
			
		||||
 | 
			
		||||
    it "raises an exception when policy_scope is not used" do
 | 
			
		||||
      expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_policy_authorized?" do
 | 
			
		||||
    it "is true when authorized" do
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      expect(controller.pundit_policy_authorized?).to be true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "is false when not authorized" do
 | 
			
		||||
      expect(controller.pundit_policy_authorized?).to be false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_policy_scoped?" do
 | 
			
		||||
    it "is true when policy_scope is used" do
 | 
			
		||||
      controller.policy_scope(Post)
 | 
			
		||||
      expect(controller.pundit_policy_scoped?).to be true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "is false when policy scope is not used" do
 | 
			
		||||
      expect(controller.pundit_policy_scoped?).to be false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#authorize" do
 | 
			
		||||
    it "infers the policy name and authorizes based on it" do
 | 
			
		||||
      expect(controller.authorize(post)).to be_truthy
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record on successful authorization" do
 | 
			
		||||
      expect(controller.authorize(post)).to eq(post)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record when passed record with namespace " do
 | 
			
		||||
      expect(controller.authorize([:project, comment], :update?)).to eq(comment)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the record when passed record with nested namespace " do
 | 
			
		||||
      expect(controller.authorize([:project, :admin, comment], :update?)).to eq(comment)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the policy name symbol when passed record with headless policy" do
 | 
			
		||||
      expect(controller.authorize(:publication, :create?)).to eq(:publication)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "returns the class when passed record not a particular instance" do
 | 
			
		||||
      expect(controller.authorize(Post, :show?)).to eq(Post)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be given a different permission to check" do
 | 
			
		||||
      expect(controller.authorize(post, :show?)).to be_truthy
 | 
			
		||||
      expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be given a different policy class" do
 | 
			
		||||
      expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be given a different policy class using namespaces" do
 | 
			
		||||
      expect(PublicationPolicy).to receive(:new).with(user, comment).and_call_original
 | 
			
		||||
      expect(controller.authorize([:project, comment], :create?, policy_class: PublicationPolicy)).to eql(comment)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "works with anonymous class policies" do
 | 
			
		||||
      expect(controller.authorize(article_tag, :show?)).to be_truthy
 | 
			
		||||
      expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception when the permission check fails" do
 | 
			
		||||
      expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception when a policy cannot be found" do
 | 
			
		||||
      expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "caches the policy" do
 | 
			
		||||
      expect(controller.policies[post]).to be_nil
 | 
			
		||||
      controller.authorize(post)
 | 
			
		||||
      expect(controller.policies[post]).not_to be_nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error when the given record is nil" do
 | 
			
		||||
      expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy constructor" do
 | 
			
		||||
      expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#skip_authorization" do
 | 
			
		||||
    it "disables authorization verification" do
 | 
			
		||||
      controller.skip_authorization
 | 
			
		||||
      expect { controller.verify_authorized }.not_to raise_error
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#skip_policy_scope" do
 | 
			
		||||
    it "disables policy scope verification" do
 | 
			
		||||
      controller.skip_policy_scope
 | 
			
		||||
      expect { controller.verify_policy_scoped }.not_to raise_error
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#pundit_user" do
 | 
			
		||||
    it "returns the same thing as current_user" do
 | 
			
		||||
      expect(controller.pundit_user).to eq controller.current_user
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#policy" do
 | 
			
		||||
    it "returns an instantiated policy" do
 | 
			
		||||
      policy = controller.policy(post)
 | 
			
		||||
      expect(policy.user).to eq user
 | 
			
		||||
      expect(policy.post).to eq post
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception if the given policy can't be found" do
 | 
			
		||||
      expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy constructor" do
 | 
			
		||||
      expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy to be injected" do
 | 
			
		||||
      new_policy = OpenStruct.new
 | 
			
		||||
      controller.policies[post] = new_policy
 | 
			
		||||
 | 
			
		||||
      expect(controller.policy(post)).to eq new_policy
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#policy_scope" do
 | 
			
		||||
    it "returns an instantiated policy scope" do
 | 
			
		||||
      expect(controller.policy_scope(Post)).to eq :published
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy scope class to be overriden" do
 | 
			
		||||
      expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "throws an exception if the given policy can't be found" do
 | 
			
		||||
      expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "raises an error with a invalid policy scope constructor" do
 | 
			
		||||
      expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "allows policy_scope to be injected" do
 | 
			
		||||
      new_scope = OpenStruct.new
 | 
			
		||||
      controller.policy_scopes[Post] = new_scope
 | 
			
		||||
 | 
			
		||||
      expect(controller.policy_scope(Post)).to eq new_scope
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#permitted_attributes" do
 | 
			
		||||
    it "checks policy for permitted attributes" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(
 | 
			
		||||
        "title" => "Hello",
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
      expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq("votes" => 5)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "checks policy for permitted attributes for record of a ActiveModel type" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        customer_post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(
 | 
			
		||||
        "title" => "Hello",
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
      expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(
 | 
			
		||||
        "votes" => 5
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "#permitted_attributes_for_action" do
 | 
			
		||||
    it "is checked if it is defined in the policy" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          body: "blah",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "revise"
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq("body" => "blah")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "can be explicitly set" do
 | 
			
		||||
      params = ActionController::Parameters.new(
 | 
			
		||||
        post: {
 | 
			
		||||
          title: "Hello",
 | 
			
		||||
          body: "blah",
 | 
			
		||||
          votes: 5,
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      action = "update"
 | 
			
		||||
      expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq("body" => "blah")
 | 
			
		||||
      expect(Pundit).to have_received(:warn).with start_with("[DEPRECATION]")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -200,10 +200,10 @@ class DenierPolicy < Struct.new(:user, :record)
 | 
			
		|||
end
 | 
			
		||||
 | 
			
		||||
class Controller
 | 
			
		||||
  include Pundit
 | 
			
		||||
  include Pundit::Authorization
 | 
			
		||||
  # Mark protected methods public so they may be called in test
 | 
			
		||||
  # rubocop:disable Style/AccessModifierDeclarations
 | 
			
		||||
  public(*Pundit.protected_instance_methods)
 | 
			
		||||
  public(*Pundit::Authorization.protected_instance_methods)
 | 
			
		||||
  # rubocop:enable Style/AccessModifierDeclarations
 | 
			
		||||
 | 
			
		||||
  attr_reader :current_user, :action_name, :params
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue