Git Product home page Git Product logo

Comments (4)

palkan avatar palkan commented on August 27, 2024

Yeah, that's a tricky thing.

I have an idea which solves this particular case (but not sure that's it's clear):

  • when check?(:smth) is called on the same record/policy, we only add { current_policy => [:smth] } to reasons
  • when check?(:smth, other_record) is called, we "unwrap" sub-policy reasons if any, i.e. { sub_policy => [:some_reason] }; if no reasons then { sub_policy => [:smth] }.

Example:

class DependeePolicy
  def do_it?
    check?(:a?) && check?(:b?)
  end

  def do_that?
      b? || c?
  end

  def a?
    true
  end

  def b?
    false
  end

  def c?
    false
  end
end

class DependerPolicy
  def do_it?
    check?(:do_it?, record.dependee) && check?(:c?)
  end

  def do_that?
    check?(:do_that?, record.dependee) || check?(:d?)
  end

  def c?
    true
  end

  def d?
    false
  end
end

# first case: self-check
begin
  authorize! dependee, to: :do_it?
rescue ActionPolicy::Unauthorized => e
  puts e.result.reasons.details # { :dependee => [:b?] }
end

# 1: self-check
begin
  authorize! dependee, to: :do_it?
rescue ActionPolicy::Unauthorized => e
  puts e.result.reasons.details # { :dependee => [:b?] }
end

# 2: no checks
begin
  authorize! dependee, to: :do_that?
rescue ActionPolicy::Unauthorized => e
  puts e.result.reasons.details # {}
end

# 3: sub-policy check with sub-checks
begin
  authorize! depender, to: :do_it?
rescue ActionPolicy::Unauthorized => e
  puts e.result.reasons.details # { :dependee => [:b?] }
end

# 3: sub-policy check without sub-checks
begin
  authorize! depender, to: :do_that?
rescue ActionPolicy::Unauthorized => e
  # NOTE: we use dependee rule as reason, 'cause no reasons were populated in sub-call
  puts e.result.reasons.details # { :dependee => [:do_that?], :depender => [:d?] }
end

from action_policy.

adisandro avatar adisandro commented on August 27, 2024

Apologies for the late reply.
What you propose make sense, except maybe for example 2. Shouldn't it return { :dependee => [:do_that?] } too? (i.e. the "external" authorize! acting like a check? call?)
I may be wrong here because I don't have a policy like that in our code, so I haven't tried.

from action_policy.

palkan avatar palkan commented on August 27, 2024

What you propose make sense, except maybe for example 2. Shouldn't it return { :dependee => [:do_that?] } too?

Reasons are only populated when check? or allowed_to? is used.

External authorize! populates e.result.policy, e.result.rule and e.result.message (which would contain DependeePolicy and :do_that?).

The idea of reasons is to specify the failure cause more precisely and not to replace the top-level "reason" (i.e. a rule that failed).

We use both e.result.message and e.result.reasons.full_messages` for displaying errors, like that:

begin
  authorize! dependee, to: :do_it?
rescue ActionPolicy::Unauthorized => e
  msg = e.result.message

  if e.result.reasons.any?
    msg << ": #{e.result.reasons.full_messages.map(&:downcase).join(', ')}"
  end

  puts msg
end

from action_policy.

adisandro avatar adisandro commented on August 27, 2024

Thank you for the clarification!

from action_policy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.