You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.0KB

  1. module CryptCheck
  2. module State
  3. def states
  4. # Remove duplicated test for each level
  5. @states ||= State.empty.merge(self.checks.group_by { |c| c[1] }.collect do |level, checks|
  6. states = checks.group_by(&:first).collect do |name, checks|
  7. states = checks.collect &:last
  8. # true > false > nil
  9. state = if states.include? true
  10. true
  11. elsif states.include? false
  12. false
  13. else
  14. nil
  15. end
  16. [name, state]
  17. end.to_h
  18. [level, states]
  19. end.to_h)
  20. end
  21. def status
  22. @status ||= State.status self.checks.select { |c| c.last == true }.collect { |c| c[1] }
  23. end
  24. BADS = %i(critical error warning).freeze
  25. GOODS = %i(good great best).freeze
  26. LEVELS = (BADS + GOODS).freeze
  27. def self.good?(level)
  28. GOODS.include? level
  29. end
  30. def self.bad?(level)
  31. BADS.include? level
  32. end
  33. extend Enumerable
  34. def self.each(&block)
  35. LEVELS.each &block
  36. end
  37. def self.empty
  38. self.collect { |s| [s, {}] }.to_h
  39. end
  40. def self.status(states)
  41. states = self.convert states
  42. self.min LEVELS, states
  43. end
  44. class << self
  45. alias_method :'[]', :status
  46. end
  47. def self.problem(states)
  48. states = self.convert states
  49. self.min BADS, states
  50. end
  51. def self.sort(states)
  52. states.sort { |a, b| self.compare a, b }
  53. end
  54. def self.compare(a, b)
  55. a = LEVELS.find_index(a.status) || (LEVELS.size - 1) / 2.0
  56. b = LEVELS.find_index(b.status) || (LEVELS.size - 1) / 2.0
  57. a <=> b
  58. end
  59. protected
  60. def checks
  61. @checks ||= self.available_checks.collect { |c| perform_check c }.flatten(1) + children.collect(&:checks).flatten(1)
  62. end
  63. private
  64. def self.convert(status)
  65. status = [status] unless status.respond_to? :first
  66. first = status.first
  67. status = status.collect &:status if first.respond_to? :status
  68. status
  69. end
  70. def self.min(levels, states)
  71. return nil if states.empty?
  72. (levels & states).first
  73. end
  74. def self.max(levels, states)
  75. return nil if states.empty?
  76. (levels & states).last
  77. end
  78. def self.merge(*states)
  79. State.collect do |s|
  80. state = states.collect { |ss| ss.fetch s, [] }
  81. .inject(&:+).uniq
  82. [s, state]
  83. end.to_h
  84. end
  85. def children
  86. []
  87. end
  88. def perform_check(check)
  89. name, levels, check = check
  90. result = check.call self
  91. case levels
  92. when Symbol # Expected result is true/false/nil
  93. return [[name, levels, result]]
  94. else # Expected result is the best/worst case
  95. # N/A, so return all levels as N/A
  96. return levels.collect { |l| [name, l, nil] } if result.nil?
  97. checks = []
  98. if BADS.include? result
  99. checks += (GOODS & levels).collect { |l| [name, l, false] }
  100. index = BADS.index result
  101. checks += (BADS & levels).collect { |l| [name, l, BADS.index(l) >= index] }
  102. else
  103. checks += (BADS & levels).collect { |l| [name, l, false] }
  104. index = GOODS.index result
  105. checks += (GOODS & levels).collect { |l| [name, l, GOODS.index(l) <= index] }
  106. end
  107. return checks
  108. end
  109. end
  110. end
  111. end