Skip to content

Commit

Permalink
Merge pull request #842 from varvet/kbs/update-documentation
Browse files Browse the repository at this point in the history
Janitorial: Add documentation to most things
  • Loading branch information
Burgestrand authored Nov 25, 2024
2 parents 54cc64e + 3cbe44f commit a82833b
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 3 deletions.
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ end

YARD::Rake::YardocTask.new do |t|
t.files = ["lib/**/*.rb"]
t.stats_options = ["--list-undoc"]
end

task default: :spec
1 change: 1 addition & 0 deletions lib/generators/rspec/policy_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
module Rspec
# @private
module Generators
# @private
class PolicyGenerator < ::Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)

Expand Down
1 change: 1 addition & 0 deletions lib/generators/test_unit/policy_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
module TestUnit
# @private
module Generators
# @private
class PolicyGenerator < ::Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)

Expand Down
27 changes: 25 additions & 2 deletions lib/pundit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "pundit/policy_finder"
require "pundit/authorization"
require "pundit/context"
require "pundit/cache_store"
require "pundit/cache_store/null_store"
require "pundit/cache_store/legacy_store"

Expand All @@ -14,6 +15,8 @@
# keep it here with compact class style definition.
class Pundit::Error < StandardError; end # rubocop:disable Style/ClassAndModuleChildren

# Hello? Yes, this is Pundit.
#
# @api public
module Pundit
# @api private
Expand All @@ -26,8 +29,24 @@ module Generators; end

# Error that will be raised when authorization has failed
class NotAuthorizedError < Error
attr_reader :query, :record, :policy

# @see #initialize
attr_reader :query
# @see #initialize
attr_reader :record
# @see #initialize
attr_reader :policy

# @overload initialize(message)
# Create an error with a simple error message.
# @param [String] message A simple error message string.
#
# @overload initialize(options)
# Create an error with the specified attributes.
# @param [Hash] options The error options.
# @option options [String] :message Optional custom error message. Will default to a generalized message.
# @option options [Symbol] :query The name of the policy method that was checked.
# @option options [Object] :record The object that was being checked with the policy.
# @option options [Class] :policy The class of policy that was used for the check.
def initialize(options = {})
if options.is_a? String
message = options
Expand Down Expand Up @@ -103,8 +122,12 @@ def policy!(user, *args, **kwargs, &block)
end
end

# Rails view helpers, to allow a slightly different view-specific
# implementation of the methods in {Pundit::Authorization}.
#
# @api private
module Helper
# @see Pundit::Authorization#pundit_policy_scope
def policy_scope(scope)
pundit_policy_scope(scope)
end
Expand Down
9 changes: 9 additions & 0 deletions lib/pundit/authorization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,15 @@ def policy_scopes

# rubocop:enable Naming/MemoizedInstanceVariableName

# This was added to allow calling `policy_scope!` without flipping the
# `pundit_policy_scoped?` flag.
#
# It's used internally by `policy_scope`, as well as from the views
# when they call `policy_scope`. It works because views get their helper
# from {Pundit::Helper}.
#
# @note This also memoizes the instance with `scope` as the key.
# @see Pundit::Helper#policy_scope
# @api private
def pundit_policy_scope(scope)
policy_scopes[scope] ||= pundit.policy_scope!(scope)
Expand Down
22 changes: 22 additions & 0 deletions lib/pundit/cache_store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Pundit
# Namespace for cache store implementations.
#
# Cache stores are used to cache policy lookups, so you get the same policy
# instance for the same record.
module CacheStore
# @!group Cache Store Interface

# @!method fetch(user:, record:, &block)
# Looks up a stored policy or generate a new one.
#
# @note This is a method template, but the method does not exist in this module.
# @param user [Object] the user that initiated the action
# @param record [Object] the object being accessed
# @param block [Proc] the block to execute if missing
# @return [Object] the policy

# @!endgroup
end
end
3 changes: 3 additions & 0 deletions lib/pundit/cache_store/legacy_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def initialize(hash = {})
@store = hash
end

# A cache store that uses only the record as a cache key, and ignores the user.
#
# @note `nil` results are not cached.
def fetch(user:, record:)
_ = user
@store[record] ||= yield
Expand Down
3 changes: 3 additions & 0 deletions lib/pundit/cache_store/null_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class << self
attr_reader :instance
end

# Always yields, does not cache anything.
# @yield
# @return [any] whatever the block returns.
def fetch(*, **)
yield
end
Expand Down
17 changes: 17 additions & 0 deletions lib/pundit/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def initialize(user:, policy_cache: CacheStore::NullStore.instance)
attr_reader :user

# @api private
# @see #initialize
attr_reader :policy_cache

# @!group Policies
Expand Down Expand Up @@ -134,6 +135,15 @@ def policy_scope!(scope)

# @!group Private Helpers

# Finds a cached policy for the given record, or yields to find one.
#
# @api private
# @param record [Object] the object we're retrieving the policy for
# @yield a policy finder if no policy was cached
# @yieldparam [PolicyFinder] policy_finder
# @yieldreturn [#new(user, model)]
# @return [Policy, nil] an instantiated policy
# @raise [InvalidConstructorError] if policy can't be instantated
def cached_find(record)
policy_cache.fetch(user: user, record: record) do
klass = yield policy_finder(record)
Expand All @@ -149,10 +159,17 @@ def cached_find(record)
end
end

# Return a policy finder for the given record.
#
# @api private
# @return [PolicyFinder]
def policy_finder(record)
PolicyFinder.new(record)
end

# Given a possibly namespaced record, return the actual record.
#
# @api private
def pundit_model(record)
record.is_a?(Array) ? record.last : record
end
Expand Down
17 changes: 16 additions & 1 deletion lib/pundit/policy_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ module Pundit
# finder.scope #=> UserPolicy::Scope
#
class PolicyFinder
# A constant applied to the end of the class name to find the policy class.
#
# @api private
SUFFIX = "Policy"

# @see #initialize
attr_reader :object

# @param object [any] the object to find policy and scope classes for
#
def initialize(object)
@object = object
end
Expand Down Expand Up @@ -76,6 +78,11 @@ def param_key # rubocop:disable Metrics/AbcSize

private

# Given an object, find the policy class name.
#
# Uses recursion to handle namespaces.
#
# @return [String, Class] the policy class, or its name.
def find(subject)
if subject.is_a?(Array)
modules = subject.dup
Expand All @@ -92,6 +99,14 @@ def find(subject)
end
end

# Given an object, find its' class name.
#
# - Supports ActiveModel.
# - Supports regular classes.
# - Supports symbols.
# - Supports object instances.
#
# @return [String, Class] the class, or its name.
def find_class_name(subject)
if subject.respond_to?(:model_name)
subject.model_name
Expand Down
2 changes: 2 additions & 0 deletions lib/pundit/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
require "active_support/core_ext/array/conversions"

module Pundit
# Namespace for Pundit's RSpec integration.
module RSpec
# Namespace for Pundit's RSpec matchers.
module Matchers
extend ::RSpec::Matchers::DSL

Expand Down
1 change: 1 addition & 0 deletions lib/pundit/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

module Pundit
# The current version of Pundit.
VERSION = "2.4.0"
end

0 comments on commit a82833b

Please sign in to comment.