|
|
|
|
module CryptCheck
|
|
|
|
|
module State
|
|
|
|
|
def states
|
|
|
|
|
# Remove duplicated test for each level
|
|
|
|
|
@states ||= State.empty.merge(self.checks.group_by { |c| c[1] }.collect do |level, checks|
|
|
|
|
|
states = checks.group_by(&:first).collect do |name, checks|
|
|
|
|
|
states = checks.collect &:last
|
|
|
|
|
# true > false > nil
|
|
|
|
|
state = if states.include? true
|
|
|
|
|
true
|
|
|
|
|
elsif states.include? false
|
|
|
|
|
false
|
|
|
|
|
else
|
|
|
|
|
nil
|
|
|
|
|
end
|
|
|
|
|
[name, state]
|
|
|
|
|
end.to_h
|
|
|
|
|
[level, states]
|
|
|
|
|
end.to_h)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def status
|
|
|
|
|
@status ||= State.status self.checks.select { |c| c.last == true }.collect { |c| c[1] }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
BADS = %i(critical error warning).freeze
|
|
|
|
|
GOODS = %i(good great best).freeze
|
|
|
|
|
LEVELS = (BADS + GOODS).freeze
|
|
|
|
|
|
|
|
|
|
def self.good?(level)
|
|
|
|
|
GOODS.include? level
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.bad?(level)
|
|
|
|
|
BADS.include? level
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.good_or_bad(level)
|
|
|
|
|
if self.good?(level)
|
|
|
|
|
:good
|
|
|
|
|
else
|
|
|
|
|
:bad
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.state(states, level)
|
|
|
|
|
state =states[level].values.uniq
|
|
|
|
|
case State.good_or_bad(level)
|
|
|
|
|
when :bad
|
|
|
|
|
if state.include? true
|
|
|
|
|
true
|
|
|
|
|
else
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
when :good
|
|
|
|
|
if state.include? false
|
|
|
|
|
if state.include? true
|
|
|
|
|
:some
|
|
|
|
|
else
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
:all
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
extend Enumerable
|
|
|
|
|
|
|
|
|
|
def self.each(&block)
|
|
|
|
|
LEVELS.each &block
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.empty
|
|
|
|
|
self.collect { |s| [s, {}] }.to_h
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.status(states)
|
|
|
|
|
states = self.convert states
|
|
|
|
|
self.min LEVELS, states
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
class << self
|
|
|
|
|
alias_method :'[]', :status
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.problem(states)
|
|
|
|
|
states = self.convert states
|
|
|
|
|
self.min BADS, states
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.sort(states)
|
|
|
|
|
states.sort { |a, b| self.compare a, b }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.compare(a, b)
|
|
|
|
|
a = LEVELS.find_index(a.status) || (LEVELS.size - 1) / 2.0
|
|
|
|
|
b = LEVELS.find_index(b.status) || (LEVELS.size - 1) / 2.0
|
|
|
|
|
b <=> a
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
def checks
|
|
|
|
|
@checks ||= self.available_checks.collect { |c| perform_check c }.flatten(1) + children.collect(&:checks).flatten(1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
def self.convert(status)
|
|
|
|
|
status = [status] unless status.respond_to? :first
|
|
|
|
|
first = status.first
|
|
|
|
|
status = status.collect &:status if first.respond_to? :status
|
|
|
|
|
status
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.min(levels, states)
|
|
|
|
|
return nil if states.empty?
|
|
|
|
|
(levels & states).first
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.max(levels, states)
|
|
|
|
|
return nil if states.empty?
|
|
|
|
|
(levels & states).last
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.merge(*states)
|
|
|
|
|
State.collect do |s|
|
|
|
|
|
state = states.collect { |ss| ss.fetch s, [] }
|
|
|
|
|
.inject(&:+).uniq
|
|
|
|
|
[s, state]
|
|
|
|
|
end.to_h
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def children
|
|
|
|
|
[]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def perform_check(check)
|
|
|
|
|
name, levels, check = check
|
|
|
|
|
result = check.call self
|
|
|
|
|
case levels
|
|
|
|
|
when Symbol # Expected result is true/false/nil
|
|
|
|
|
return [[name, levels, result]]
|
|
|
|
|
else # Expected result is the best/worst case
|
|
|
|
|
# N/A, so return all levels as N/A
|
|
|
|
|
return levels.collect { |l| [name, l, nil] } if result.nil?
|
|
|
|
|
|
|
|
|
|
checks = []
|
|
|
|
|
if BADS.include? result
|
|
|
|
|
checks += (GOODS & levels).collect { |l| [name, l, false] }
|
|
|
|
|
index = BADS.index result
|
|
|
|
|
checks += (BADS & levels).collect { |l| [name, l, BADS.index(l) >= index] }
|
|
|
|
|
else
|
|
|
|
|
checks += (BADS & levels).collect { |l| [name, l, false] }
|
|
|
|
|
index = GOODS.index result
|
|
|
|
|
checks += (GOODS & levels).collect { |l| [name, l, GOODS.index(l) <= index] }
|
|
|
|
|
end
|
|
|
|
|
return checks
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|