diff options
Diffstat (limited to 'app/finders/concerns/finder_methods.rb')
-rw-r--r-- | app/finders/concerns/finder_methods.rb | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/app/finders/concerns/finder_methods.rb b/app/finders/concerns/finder_methods.rb new file mode 100644 index 00000000000..2e905fa5750 --- /dev/null +++ b/app/finders/concerns/finder_methods.rb @@ -0,0 +1,51 @@ +module FinderMethods + def find_by!(*args) + raise_not_found_unless_authorized execute.find_by!(*args) + end + + def find_by(*args) + if_authorized execute.find_by(*args) + end + + def find(*args) + raise_not_found_unless_authorized model.find(*args) + end + + private + + def raise_not_found_unless_authorized(result) + result = if_authorized(result) + + raise ActiveRecord::RecordNotFound.new("Couldn't find #{model}") unless result + + result + end + + def if_authorized(result) + # Return the result if the finder does not perform authorization checks. + # this is currently the case in the `MilestoneFinder` + return result unless respond_to?(:current_user) + + if can_read_object?(result) + result + else + nil + end + end + + def can_read_object?(object) + # When there's no policy, we'll allow the read, this is for example the case + # for Todos + return true unless DeclarativePolicy.has_policy?(object) + + model_name = object&.model_name || model.model_name + + Ability.allowed?(current_user, :"read_#{model_name.singular}", object) + end + + # This fetches the model from the `ActiveRecord::Relation` but does not + # actually execute the query. + def model + execute.model + end +end |