Class Authorization::DevelopmentSupport::ChangeSupporter
In: lib/declarative_authorization/development_support/change_supporter.rb
Parent: AbstractAnalyzer

Ideas for improvement

  • Algorithm
    • Objective function:
      • affected user count,
      • as specific as possible (roles, privileges)
      • as little changes as necessary
    • Modify role, privilege hierarchy
    • Merge, split roles
    • Add privilege to existing rules
  • Features
    • Improve review facts: impact, affected users count
    • group similar candidates: only show abstract methods?
    • restructure GUI layout: more room for analyzing suggestions
    • changelog, previous tests, etc.
    • multiple permissions in tests
  • Evaluation of approaches with Analyzer algorithms
  • Authorization constraints

Algorithm

  • for each candidate
    • abstract actions: solving first failing test (remove privilege from role)
    • for each abstract action
      • specific actions: concrete steps (remove privilege from specific role)
      • for each specific action
        • next if reversal action of previous step
        • apply specific action on candidate
        • save as solution if no failing tests on changed_candidate
        • else: queue as candidate
  • equivalent states

NOTE:

  • user.clone needs to clone role_symbols
  • user.role_symbols needs to respond to <<
  • user.login is needed

Methods

Classes and Modules

Class Authorization::DevelopmentSupport::ChangeSupporter::AbstractAction
Class Authorization::DevelopmentSupport::ChangeSupporter::AbstractCompoundAction
Class Authorization::DevelopmentSupport::ChangeSupporter::AddPrivilegeAndAssignRoleToUserAction
Class Authorization::DevelopmentSupport::ChangeSupporter::Approach
Class Authorization::DevelopmentSupport::ChangeSupporter::ApproachChecker
Class Authorization::DevelopmentSupport::ChangeSupporter::AssignPrivilegeToRoleAction
Class Authorization::DevelopmentSupport::ChangeSupporter::AssignRoleToUserAction
Class Authorization::DevelopmentSupport::ChangeSupporter::CreateAndAssignRoleToUserAction
Class Authorization::DevelopmentSupport::ChangeSupporter::GroupedApproach
Class Authorization::DevelopmentSupport::ChangeSupporter::RemovePrivilegeFromRoleAction
Class Authorization::DevelopmentSupport::ChangeSupporter::RemoveRoleFromUserAction
Class Authorization::DevelopmentSupport::ChangeSupporter::Test

Protected Class methods

[Source]

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

Public Instance methods

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.

[Source]

    # File lib/declarative_authorization/development_support/change_supporter.rb, line 48
48:       def find_approaches_for (options, &tests)
49:         @prohibited_actions = (options[:prohibited_actions] || []).to_set
50: 
51:         @approaches_by_actions = {}
52: 
53:         candidates = []
54:         suggestions = []
55:         approach_checker = ApproachChecker.new(self, tests)
56: 
57:         starting_candidate = Approach.new(@engine, options[:users], [])
58:         if starting_candidate.check(approach_checker)
59:           suggestions << starting_candidate
60:         else
61:           candidates << starting_candidate
62:         end
63: 
64:         checked_candidates = 0
65:         while !candidates.empty? and checked_candidates < 200
66:           checked_candidates += next_step(suggestions, candidates, approach_checker)
67:         end
68: 
69:         # remove subsets
70:         suggestions.sort!
71:       end

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

[Source]

    # File lib/declarative_authorization/development_support/change_supporter.rb, line 75
75:       def group_approaches (approaches)
76:         approaches.each_with_object([]) do |approach, grouped|
77:           if grouped.last and grouped.last.approach.similar_to(approach)
78:             grouped.last.similar_approaches << approach
79:           else
80:             grouped << GroupedApproach.new(approach)
81:           end
82:         end
83:       end

Protected Instance methods

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 598
598:       def add_to_approaches_by_action! (candidate)
599:         candidate.changes.each do |action|
600:           (@approaches_by_actions[action] ||= []) << candidate
601:         end
602:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 566
566:       def check_child_candidates! (approach_checker, viable_approaches, candidates, child_candidates)
567:         child_candidates.each do |child_candidate|
568:           if child_candidate.check(approach_checker)
569:             unless superset_of_existing?(child_candidate)
570:               remove_supersets!(viable_approaches, child_candidate)
571:               viable_approaches << child_candidate
572:               add_to_approaches_by_action!(child_candidate)
573:             end
574:           else
575:             candidates << child_candidate
576:           end
577:           child_candidate.freeze
578:         end
579:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 550
550:       def generate_child_candidates (candidate)
551:         child_candidates = []
552:         abstract_actions = candidate.abstract_actions
553:         abstract_actions.each do |abstract_action|
554:           abstract_action.specific_actions(candidate).each do |specific_action|
555:             child_candidate = candidate.dup
556:             if !specific_action.resembles_any?(@prohibited_actions) and
557:                   !child_candidate.reverse_of_previous?(specific_action) and
558:                   child_candidate.apply(specific_action)
559:               child_candidates << child_candidate
560:             end
561:           end
562:         end
563:         child_candidates
564:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 540
540:       def next_step (viable_approaches, candidates, approach_checker)
541:         candidate = candidates.shift
542: 
543:         child_candidates = generate_child_candidates(candidate)
544:         check_child_candidates!(approach_checker, viable_approaches, candidates, child_candidates)
545: 
546:         candidates.sort!
547:         child_candidates.length
548:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 610
610:       def relevant_roles (approach)
611:         self.class.relevant_roles(approach)
612:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 604
604:       def remove_from_approaches_by_action! (candidate)
605:         candidate.changes.each do |action|
606:           (@approaches_by_actions[action] ||= []).delete(candidate)
607:         end
608:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 587
587:       def remove_supersets! (existing, candidate)
588:         candidate.changes.inject([]) do |memo, action|
589:           memo += (@approaches_by_actions[action] ||= []).select do |approach|
590:             candidate.subset?(approach)
591:           end
592:         end.uniq.each do |approach|
593:           existing.delete(approach)
594:           remove_from_approaches_by_action!(approach)
595:         end
596:       end

[Source]

     # File lib/declarative_authorization/development_support/change_supporter.rb, line 581
581:       def superset_of_existing? (candidate)
582:         candidate.changes.any? do |action|
583:           (@approaches_by_actions[action] ||= []).any? {|approach| approach.subset?(candidate)}
584:         end
585:       end

[Validate]