class Authorization::DevelopmentSupport::ChangeSupporter

Ideas for improvement

Algorithm

NOTE:

Protected Class Methods

relevant_roles(approach) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 613
def self.relevant_roles (approach)
  (AnalyzerEngine.relevant_roles(approach.engine, approach.users) +
      (approach.engine.roles.include?(:new_role_for_change_analyzer) ?
         [AnalyzerEngine::Role.for_sym(:new_role_for_change_analyzer, approach.engine)] : [])).uniq
end

Public Instance Methods

find_approaches_for(options, &tests) click to toggle source

Returns a list of possible approaches for changes to the current authorization rules that achieve a given goal. The goal is given as permission tests in the block. The instance method users is available when the block is executed to refer to the then-current users, whose roles might have changed as one suggestion.

# File lib/declarative_authorization/development_support/change_supporter.rb, line 48
def find_approaches_for (options, &tests)
  @prohibited_actions = (options[:prohibited_actions] || []).to_set

  @approaches_by_actions = {}

  candidates = []
  suggestions = []
  approach_checker = ApproachChecker.new(self, tests)

  starting_candidate = Approach.new(@engine, options[:users], [])
  if starting_candidate.check(approach_checker)
    suggestions << starting_candidate
  else
    candidates << starting_candidate
  end

  checked_candidates = 0
  while !candidates.empty? and checked_candidates < 200
    checked_candidates += next_step(suggestions, candidates, approach_checker)
  end

  # remove subsets
  suggestions.sort!
end
group_approaches(approaches) click to toggle source

Returns an array of GroupedApproaches for the given array of approaches. Only groups directly adjacent approaches

# File lib/declarative_authorization/development_support/change_supporter.rb, line 75
def group_approaches (approaches)
  approaches.each_with_object([]) do |approach, grouped|
    if grouped.last and grouped.last.approach.similar_to(approach)
      grouped.last.similar_approaches << approach
    else
      grouped << GroupedApproach.new(approach)
    end
  end
end

Protected Instance Methods

add_to_approaches_by_action!(candidate) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 598
def add_to_approaches_by_action! (candidate)
  candidate.changes.each do |action|
    (@approaches_by_actions[action] ||= []) << candidate
  end
end
check_child_candidates!(approach_checker, viable_approaches, candidates, child_candidates) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 566
def check_child_candidates! (approach_checker, viable_approaches, candidates, child_candidates)
  child_candidates.each do |child_candidate|
    if child_candidate.check(approach_checker)
      unless superset_of_existing?(child_candidate)
        remove_supersets!(viable_approaches, child_candidate)
        viable_approaches << child_candidate
        add_to_approaches_by_action!(child_candidate)
      end
    else
      candidates << child_candidate
    end
    child_candidate.freeze
  end
end
generate_child_candidates(candidate) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 550
def generate_child_candidates (candidate)
  child_candidates = []
  abstract_actions = candidate.abstract_actions
  abstract_actions.each do |abstract_action|
    abstract_action.specific_actions(candidate).each do |specific_action|
      child_candidate = candidate.dup
      if !specific_action.resembles_any?(@prohibited_actions) and
            !child_candidate.reverse_of_previous?(specific_action) and
            child_candidate.apply(specific_action)
        child_candidates << child_candidate
      end
    end
  end
  child_candidates
end
next_step(viable_approaches, candidates, approach_checker) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 540
def next_step (viable_approaches, candidates, approach_checker)
  candidate = candidates.shift

  child_candidates = generate_child_candidates(candidate)
  check_child_candidates!(approach_checker, viable_approaches, candidates, child_candidates)

  candidates.sort!
  child_candidates.length
end
relevant_roles(approach) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 610
def relevant_roles (approach)
  self.class.relevant_roles(approach)
end
remove_from_approaches_by_action!(candidate) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 604
def remove_from_approaches_by_action! (candidate)
  candidate.changes.each do |action|
    (@approaches_by_actions[action] ||= []).delete(candidate)
  end
end
remove_supersets!(existing, candidate) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 587
def remove_supersets! (existing, candidate)
  candidate.changes.inject([]) do |memo, action|
    memo += (@approaches_by_actions[action] ||= []).select do |approach|
      candidate.subset?(approach)
    end
  end.uniq.each do |approach|
    existing.delete(approach)
    remove_from_approaches_by_action!(approach)
  end
end
superset_of_existing?(candidate) click to toggle source
# File lib/declarative_authorization/development_support/change_supporter.rb, line 581
def superset_of_existing? (candidate)
  candidate.changes.any? do |action|
    (@approaches_by_actions[action] ||= []).any? {|approach| approach.subset?(candidate)}
  end
end