Method: Ability.forgetting
- Defined in:
- app/models/ability.rb
.forgetting(pattern, &block) ⇒ Object
This method is something of a band-aid over the problem. The problem is that some conditions may not be re-entrant, if facts change. (‘BasePolicy#admin?` is a known offender, due to the effects of admin_mode)
To deal with this we need to clear two elements of state: the offending conditions (selected by ‘pattern’) and the cached ability checks (cached on the ‘policy#runner(ability)`).
Clearing the conditions (see forget_all_but) is fairly robust, provided the pattern is not under-selective. Clearing the runners is harder, since there is not good way to know which abilities any given condition may affect. The approach taken here (see forget_runner_result) is to discard all runner results generated during a forgetting block. This may be under-selective if a runner prior to this block cached a state value that might now be invalid.
TODO: add some kind of reverse-dependency mapping in DeclarativePolicy See: gitlab.com/gitlab-org/declarative-policy/-/issues/14
147 148 149 150 151 152 153 154 155 156 |
# File 'app/models/ability.rb', line 147 def forgetting(pattern, &block) was_forgetting = ability_forgetting? ::Gitlab::SafeRequestStore[:ability_forgetting] = true keys_before = ::Gitlab::SafeRequestStore.storage.keys yield ensure ::Gitlab::SafeRequestStore[:ability_forgetting] = was_forgetting forget_all_but(keys_before, matching: pattern) end |