def next_step (viable_approaches, candidates, approach_checker,
privilege, context, strategy)
candidate = candidates.shift
next_in_strategy = strategy[candidate.steps.length % strategy.length]
return if @seen_states.include?([candidate.state_hash, next_in_strategy])
@seen_states << [candidate.state_hash, next_in_strategy]
candidate.steps << [next_in_strategy]
candidates << candidate
new_approaches = []
case next_in_strategy
when :add_role
approach = candidate.clone_for_step(:add_role, :new_role_for_change_analyzer)
if AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
new_approaches << approach
end
when :assign_role_to_user
candidate.users.each do |user|
relevant_roles(candidate).each do |role|
next if user.role_symbols.include?(role.to_sym)
approach = candidate.clone_for_step(:assign_role_to_user, role, user)
cloned_user = user.clone
approach.users[approach.users.index(user)] = cloned_user
cloned_user.role_symbols << role.to_sym
new_approaches << approach
end
end
when :remove_role_from_user
candidate.users.each do |user|
user.role_symbols.each do |role_sym|
approach = candidate.clone_for_step(:remove_role_from_user, role_sym, user)
cloned_user = user.clone
approach.users[approach.users.index(user)] = cloned_user
cloned_user.role_symbols.delete(role_sym)
new_approaches << approach
end
end
when :add_privilege
relevant_roles(candidate).each do |role|
approach = candidate.clone_for_step(:add_privilege, privilege, context, role)
AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
new_approaches << approach
end
when :remove_privilege
relevant_roles(candidate).each do |role|
approach = candidate.clone_for_step(:remove_privilege, privilege, context, role)
if AnalyzerEngine.apply_change(approach.engine, approach.changes.last)
new_approaches << approach
end
end
else
raise "Unknown next strategy step #{next_in_strategy}"
end
new_approaches.each do |new_approach|
if new_approach.check(approach_checker)
unless viable_approaches.any? {|viable_approach| viable_approach.subset?(new_approach) }
viable_approaches.delete_if {|viable_approach| new_approach.subset?(viable_approach)}
viable_approaches << new_approach unless viable_approaches.find {|v_a| v_a.state_hash == new_approach.state_hash}
end
else
candidates << new_approach
end
end
candidates.sort!
end