diff --git a/lib/pundit.rb b/lib/pundit.rb index e234ea92..9175cb55 100644 --- a/lib/pundit.rb +++ b/lib/pundit.rb @@ -9,6 +9,8 @@ require "active_support/dependencies/autoload" require "pundit/authorization" require "pundit/context" +require "pundit/cache_store/null_store" +require "pundit/cache_store/hash_store" # @api private # To avoid name clashes with common Error naming when mixing in Pundit, @@ -66,8 +68,14 @@ def self.included(base) class << self # @see [Pundit::Context#authorize] - def authorize(user, record, query, policy_class: nil, cache: {}) - Context.new(user: user, policy_cache: cache).authorize(record, query: query, policy_class: policy_class) + def authorize(user, record, query, policy_class: nil, cache: nil) + context = if cache + Context.new(user: user, policy_cache: cache) + else + Context.new(user: user) + end + + context.authorize(record, query: query, policy_class: policy_class) end # @see [Pundit::Context#policy_scope] diff --git a/lib/pundit/authorization.rb b/lib/pundit/authorization.rb index 47f6c4ca..3377416c 100644 --- a/lib/pundit/authorization.rb +++ b/lib/pundit/authorization.rb @@ -19,7 +19,7 @@ module Authorization def pundit @pundit ||= Pundit::Context.new( user: pundit_user, - policy_cache: policies + policy_cache: Pundit::CacheStore::HashStore.new(policies) ) end diff --git a/lib/pundit/cache_store/hash_store.rb b/lib/pundit/cache_store/hash_store.rb new file mode 100644 index 00000000..e6c47f17 --- /dev/null +++ b/lib/pundit/cache_store/hash_store.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Pundit + module CacheStore + # @api private + class HashStore + def initialize(hash = {}) + @store = hash + end + + def fetch(key) + @store[key] ||= yield + end + end + end +end diff --git a/lib/pundit/cache_store/null_store.rb b/lib/pundit/cache_store/null_store.rb new file mode 100644 index 00000000..e439302d --- /dev/null +++ b/lib/pundit/cache_store/null_store.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Pundit + module CacheStore + # @api private + class NullStore + @instance = new + + class << self + attr_reader :instance + end + + def fetch(...) = yield + end + end +end diff --git a/lib/pundit/context.rb b/lib/pundit/context.rb index 0028ba1e..a3387490 100644 --- a/lib/pundit/context.rb +++ b/lib/pundit/context.rb @@ -2,7 +2,7 @@ module Pundit class Context - def initialize(user:, policy_cache: {}) + def initialize(user:, policy_cache: CacheStore::NullStore.instance) @user = user @policy_cache = policy_cache end @@ -27,7 +27,9 @@ def authorize(possibly_namespaced_record, query:, policy_class:) policy = if policy_class policy_class.new(user, record) else - policy_cache[possibly_namespaced_record] ||= policy!(possibly_namespaced_record) + policy_cache.fetch(possibly_namespaced_record) do + policy!(possibly_namespaced_record) + end end raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query)