BigW Consortium Gitlab

base_policy.rb 2.04 KB
Newer Older
1
class BasePolicy
2 3 4 5 6 7 8
  class RuleSet
    attr_reader :can_set, :cannot_set
    def initialize(can_set, cannot_set)
      @can_set = can_set
      @cannot_set = cannot_set
    end

9 10 11 12
    def size
      to_set.size
    end

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    def self.empty
      new(Set.new, Set.new)
    end

    def can?(ability)
      @can_set.include?(ability) && !@cannot_set.include?(ability)
    end

    def include?(ability)
      can?(ability)
    end

    def to_set
      @can_set - @cannot_set
    end

    def merge(other)
      @can_set.merge(other.can_set)
      @cannot_set.merge(other.cannot_set)
    end

    def can!(*abilities)
      @can_set.merge(abilities)
    end

    def cannot!(*abilities)
      @cannot_set.merge(abilities)
    end

    def freeze
      @can_set.freeze
      @cannot_set.freeze
      super
    end
  end

49 50 51 52
  def self.abilities(user, subject)
    new(user, subject).abilities
  end

53
  def self.class_for(subject)
54 55
    return GlobalPolicy if subject.nil?

56 57 58 59 60 61
    subject.class.ancestors.each do |klass|
      next unless klass.name

      begin
        policy_class = "#{klass.name}Policy".constantize

http://jneen.net/ committed
62
        # NOTE: the < operator here tests whether policy_class
63 64 65 66 67 68 69 70
        # inherits from BasePolicy
        return policy_class if policy_class < BasePolicy
      rescue NameError
        nil
      end
    end

    raise "no policy for #{subject.class.name}"
71 72
  end

73
  attr_reader :user, :subject
74 75 76 77 78 79
  def initialize(user, subject)
    @user = user
    @subject = subject
  end

  def abilities
80
    return RuleSet.empty if @user && @user.blocked?
81 82 83 84 85 86
    return anonymous_abilities if @user.nil?
    collect_rules { rules }
  end

  def anonymous_abilities
    collect_rules { anonymous_rules }
87 88
  end

89 90 91 92 93
  def anonymous_rules
    rules
  end

  def delegate!(new_subject)
94
    @rule_set.merge(Ability.allowed(@user, new_subject))
95 96
  end

97
  def can?(rule)
98
    @rule_set.can?(rule)
99 100
  end

101
  def can!(*rules)
102
    @rule_set.can!(*rules)
103 104 105
  end

  def cannot!(*rules)
106
    @rule_set.cannot!(*rules)
107
  end
108 109 110 111

  private

  def collect_rules(&b)
112
    @rule_set = RuleSet.empty
113
    yield
114
    @rule_set
115
  end
116
end