package-audit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/package/audit/cli.rb +32 -32
  3. data/lib/package/audit/const/fields.rb +4 -4
  4. data/lib/package/audit/const/file.rb +1 -0
  5. data/lib/package/audit/const/yaml.rb +13 -0
  6. data/lib/package/audit/enum/option.rb +13 -0
  7. data/lib/package/audit/enum/report.rb +12 -0
  8. data/lib/package/audit/enum/technology.rb +14 -0
  9. data/lib/package/audit/formatter/risk.rb +1 -1
  10. data/lib/package/audit/formatter/version.rb +1 -1
  11. data/lib/package/audit/formatter/version_date.rb +1 -1
  12. data/lib/package/audit/formatter/vulnerability.rb +1 -1
  13. data/lib/package/audit/{package.rb → models/package.rb} +7 -6
  14. data/lib/package/audit/npm/node_collection.rb +21 -10
  15. data/lib/package/audit/npm/vulnerability_finder.rb +1 -1
  16. data/lib/package/audit/npm/yarn_lock_parser.rb +1 -1
  17. data/lib/package/audit/ruby/bundler_specs.rb +1 -1
  18. data/lib/package/audit/ruby/gem_collection.rb +23 -6
  19. data/lib/package/audit/ruby/gem_meta_data.rb +1 -1
  20. data/lib/package/audit/ruby/vulnerability_finder.rb +1 -1
  21. data/lib/package/audit/services/command_parser.rb +103 -0
  22. data/lib/package/audit/services/package_filter.rb +39 -0
  23. data/lib/package/audit/services/package_finder.rb +58 -0
  24. data/lib/package/audit/{printer.rb → services/package_printer.rb} +12 -11
  25. data/lib/package/audit/{risk_calculator.rb → services/risk_calculator.rb} +8 -4
  26. data/lib/package/audit/technology/detector.rb +40 -0
  27. data/lib/package/audit/technology/validator.rb +56 -0
  28. data/lib/package/audit/util/summary_printer.rb +20 -9
  29. data/lib/package/audit/version.rb +1 -1
  30. data/sig/package/audit/cli.rbs +2 -0
  31. data/sig/package/audit/const/fields.rbs +2 -1
  32. data/sig/package/audit/const/file.rbs +1 -0
  33. data/sig/package/audit/const/yaml.rbs +13 -0
  34. data/sig/package/audit/enum/option.rbs +13 -0
  35. data/sig/package/audit/enum/report.rbs +12 -0
  36. data/sig/package/audit/enum/technology.rbs +12 -0
  37. data/sig/package/audit/{package.rbs → models/package.rbs} +3 -1
  38. data/sig/package/audit/{risk.rbs → models/risk.rbs} +1 -1
  39. data/sig/package/audit/npm/node_collection.rbs +4 -5
  40. data/sig/package/audit/npm/vulnerability_finder.rbs +1 -1
  41. data/sig/package/audit/ruby/gem_collection.rbs +4 -1
  42. data/sig/package/audit/services/command_parser.rbs +31 -0
  43. data/sig/package/audit/services/package_filter.rbs +19 -0
  44. data/sig/package/audit/services/package_finder.rbs +23 -0
  45. data/sig/package/audit/{printer.rbs → services/package_printer.rbs} +3 -3
  46. data/sig/package/audit/technology/detector.rbs +19 -0
  47. data/sig/package/audit/technology/validator.rbs +19 -0
  48. data/sig/package/audit/util/summary_printer.rbs +5 -5
  49. metadata +30 -14
  50. data/lib/package/audit/command_service.rb +0 -187
  51. data/sig/package/audit/command_service.rbs +0 -29
  52. /data/lib/package/audit/{risk.rb → models/risk.rb} +0 -0
  53. /data/lib/package/audit/{duplicate_package_merger.rb → services/duplicate_package_merger.rb} +0 -0
  54. /data/sig/package/audit/{duplicate_package_merger.rbs → services/duplicate_package_merger.rbs} +0 -0
  55. /data/sig/package/audit/{risk_calculator.rbs → services/risk_calculator.rbs} +0 -0
@@ -1,27 +1,28 @@
1
- require_relative 'const/fields'
2
- require_relative 'formatter/risk'
3
- require_relative 'formatter/version'
4
- require_relative 'formatter/version_date'
5
- require_relative 'formatter/vulnerability'
1
+ require_relative '../const/fields'
2
+ require_relative '../enum/option'
3
+ require_relative '../formatter/risk'
4
+ require_relative '../formatter/version'
5
+ require_relative '../formatter/version_date'
6
+ require_relative '../formatter/vulnerability'
6
7
 
7
8
  module Package
8
9
  module Audit
9
- class Printer
10
+ class PackagePrinter
10
11
  BASH_FORMATTING_REGEX = /\e\[\d+(?:;\d+)*m/
11
12
 
12
13
  COLUMN_GAP = 2
13
14
 
14
- def initialize(pkgs, options)
15
- @pkgs = pkgs
15
+ def initialize(options, pkgs)
16
16
  @options = options
17
+ @pkgs = pkgs
17
18
  end
18
19
 
19
20
  def print(fields)
20
21
  check_fields(fields)
21
22
  return if @pkgs.empty?
22
23
 
23
- if @options[:csv]
24
- csv(fields, exclude_headers: @options[:'exclude-headers'])
24
+ if @options[Enum::Option::CSV]
25
+ csv(fields, exclude_headers: @options[Enum::Option::CSV_EXCLUDE_HEADERS])
25
26
  else
26
27
  pretty(fields)
27
28
  end
@@ -38,7 +39,7 @@ module Package
38
39
  "Available fields names are: #{Const::Fields::ALL}."
39
40
  end
40
41
 
41
- def pretty(fields = Const::Fields::REPORT) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
42
+ def pretty(fields = Const::Fields::ALL) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
42
43
  # find the maximum length of each field across all the packages so we know how many
43
44
  # characters of horizontal space to allocate for each field when printing
44
45
  fields.each do |key|
@@ -1,4 +1,7 @@
1
- require_relative 'const/time'
1
+ require_relative '../const/time'
2
+ require_relative '../enum/vulnerability_type'
3
+
4
+ require 'time'
2
5
 
3
6
  module Package
4
7
  module Audit
@@ -62,12 +65,13 @@ module Package
62
65
  end
63
66
 
64
67
  def assess_deprecation_risks
68
+ risk = Risk.new(Enum::RiskType::MEDIUM, Enum::RiskExplanation::POTENTIAL_DEPRECATION)
69
+ return [risk] if @pkg.latest_version_date.nil?
70
+
65
71
  risks = []
66
72
  seconds_since_date = (Time.now - Time.parse(@pkg.latest_version_date)).to_i
67
73
 
68
- if seconds_since_date >= Const::Time::SECONDS_ELAPSED_TO_BE_OUTDATED
69
- risks << Risk.new(Enum::RiskType::MEDIUM, Enum::RiskExplanation::POTENTIAL_DEPRECATION)
70
- end
74
+ risks << risk if seconds_since_date >= Const::Time::SECONDS_ELAPSED_TO_BE_OUTDATED
71
75
  risks
72
76
  end
73
77
 
@@ -0,0 +1,40 @@
1
+ require_relative '../const/cmd'
2
+ require_relative '../const/file'
3
+ require_relative '../enum/report'
4
+ require_relative '../enum/technology'
5
+
6
+ require 'yaml'
7
+
8
+ module Package
9
+ module Audit
10
+ module Technology
11
+ class Detector
12
+ def initialize(dir)
13
+ @dir = dir
14
+ end
15
+
16
+ def detect
17
+ technologies = []
18
+ technologies << Enum::Technology::RUBY if ruby?
19
+ technologies << Enum::Technology::NODE if node?
20
+ technologies.sort
21
+ end
22
+
23
+ private
24
+
25
+ def node?
26
+ package_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_JSON}")
27
+ package_lock_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_LOCK_JSON}")
28
+ yarn_lock_present = File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
29
+ package_json_present && (package_lock_json_present || yarn_lock_present)
30
+ end
31
+
32
+ def ruby?
33
+ gemfile_present = File.exist?("#{@dir}/#{Const::File::GEMFILE}")
34
+ gemfile_lock_present = File.exist?("#{@dir}/#{Const::File::GEMFILE_LOCK}")
35
+ gemfile_present && gemfile_lock_present
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ require_relative '../const/file'
2
+ require_relative '../enum/technology'
3
+
4
+ module Package
5
+ module Audit
6
+ module Technology
7
+ class Validator
8
+ def initialize(dir)
9
+ @dir = dir
10
+ end
11
+
12
+ def validate!(technology)
13
+ case technology
14
+ when Enum::Technology::NODE
15
+ validate_node!
16
+ when Enum::Technology::RUBY
17
+ validate_ruby!
18
+ else
19
+ raise ArgumentError, "\"#{technology}\" is not a supported technology, " \
20
+ "use one of #{Enum::Technology.all}"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def validate_node!
27
+ package_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_JSON}")
28
+ package_lock_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_LOCK_JSON}")
29
+ yarn_lock_present = File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
30
+
31
+ unless package_json_present
32
+ puts Util::BashColor.red("\"#{Const::File::PACKAGE_JSON}\" was not found in #{@dir}")
33
+ end
34
+ unless package_lock_json_present || yarn_lock_present
35
+ puts Util::BashColor.red("\"#{Const::File::PACKAGE_LOCK_JSON}\" or \"#{Const::File::YARN_LOCK}\" " \
36
+ "was not found in #{@dir}")
37
+ end
38
+
39
+ exit 1 unless package_json_present && (package_lock_json_present || yarn_lock_present)
40
+ end
41
+
42
+ def validate_ruby!
43
+ gemfile_present = File.exist?("#{@dir}/#{Const::File::GEMFILE}")
44
+ gemfile_lock_present = File.exist?("#{@dir}/#{Const::File::GEMFILE_LOCK}")
45
+
46
+ puts Util::BashColor.red("\"#{Const::File::GEMFILE}\" was not found in #{@dir}") unless gemfile_present
47
+ unless gemfile_lock_present
48
+ puts Util::BashColor.red("\"#{Const::File::GEMFILE_LOCK}\" was not found in #{@dir}")
49
+ end
50
+
51
+ exit 1 unless gemfile_present && gemfile_lock_present
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -5,7 +5,7 @@ module Package
5
5
  module Audit
6
6
  module Util
7
7
  module SummaryPrinter
8
- def self.report
8
+ def self.all
9
9
  printf("\n%<info>s\n%<cmd>s\n\n",
10
10
  info: Util::BashColor.blue('To show how risk is calculated run:'),
11
11
  cmd: Util::BashColor.magenta(' > package-audit risk'))
@@ -16,26 +16,37 @@ module Package
16
16
  puts Util::BashColor.blue("Please contact the package author for more information about its status.\n")
17
17
  end
18
18
 
19
- def self.vulnerable(package_type, cmd)
19
+ def self.vulnerable(technology, cmd)
20
20
  printf("%<info>s\n%<cmd>s\n\n",
21
- info: Util::BashColor.blue("To get more information about the #{package_type} vulnerabilities run:"),
21
+ info: Util::BashColor.blue("To get more information about the #{technology} vulnerabilities run:"),
22
22
  cmd: Util::BashColor.magenta(" > #{cmd}"))
23
23
  end
24
24
 
25
- def self.total(package_type, pkgs)
26
- puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{package_type}s.\n")
25
+ def self.total(technology, report, pkgs, ignored_pkgs)
26
+ if ignored_pkgs.any?
27
+ puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages " \
28
+ "(#{ignored_pkgs.length} ignored).\n")
29
+ elsif pkgs.any?
30
+ puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages.\n")
31
+ else
32
+ puts Util::BashColor.green("There are no #{report} #{technology} packages!\n")
33
+ end
27
34
  end
28
35
 
29
- def self.statistics(package_type, pkgs)
36
+ def self.statistics(technology, report, pkgs, ignored_pkgs)
30
37
  outdated = pkgs.count(&:outdated?)
31
38
  deprecated = pkgs.count(&:deprecated?)
32
39
  vulnerable = pkgs.count(&:vulnerable?)
33
40
 
34
41
  vulnerabilities = pkgs.sum { |pkg| pkg.vulnerabilities.length }
35
42
 
36
- puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{package_type}s.\n" \
37
- "#{vulnerable} vulnerable (#{vulnerabilities} vulnerabilities), " \
38
- "#{outdated} outdated, #{deprecated} deprecated.\n")
43
+ if pkgs.any?
44
+ puts Util::BashColor.cyan("#{vulnerable} vulnerable (#{vulnerabilities} vulnerabilities), " \
45
+ "#{outdated} outdated, #{deprecated} deprecated.")
46
+ total(technology, report, pkgs, ignored_pkgs)
47
+ else
48
+ puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology} packages!\n")
49
+ end
39
50
  end
40
51
 
41
52
  def self.risk # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@@ -1,5 +1,5 @@
1
1
  module Package
2
2
  module Audit
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -9,6 +9,8 @@ module Package
9
9
 
10
10
  def report: (String) -> void
11
11
 
12
+ def respond_to_missing?: -> bool
13
+
12
14
  def risk: -> void
13
15
 
14
16
  def version: -> void
@@ -3,9 +3,10 @@ module Package
3
3
  module Const
4
4
  module Fields
5
5
  ALL: Array[Symbol]
6
+ AVAILABLE: Array[Symbol]
7
+ DEPRECATED: Array[Symbol]
6
8
  HEADERS: Hash[Symbol, String]
7
9
  OUTDATED: Array[Symbol]
8
- REPORT: Array[Symbol]
9
10
  VULNERABLE: Array[Symbol]
10
11
  end
11
12
  end
@@ -2,6 +2,7 @@ module Package
2
2
  module Audit
3
3
  module Const
4
4
  module File
5
+ CONFIG: String
5
6
  GEMFILE: String
6
7
  GEMFILE_LOCK: String
7
8
  PACKAGE_JSON: String
@@ -0,0 +1,13 @@
1
+ module Package
2
+ module Audit
3
+ module Const
4
+ module YAML
5
+ DEPRECATED: String
6
+ OUTDATED: String
7
+ TECHNOLOGY: String
8
+ VERSION: String
9
+ VULNERABLE: String
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Package
2
+ module Audit
3
+ module Enum
4
+ module Option
5
+ CONFIG: String
6
+ CSV: String
7
+ CSV_EXCLUDE_HEADERS: String
8
+ INCLUDE_IGNORED: String
9
+ TECHNOLOGY: String
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Package
2
+ module Audit
3
+ module Enum
4
+ module Report
5
+ ALL: Symbol
6
+ DEPRECATED: Symbol
7
+ OUTDATED: Symbol
8
+ VULNERABLE: Symbol
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Package
2
+ module Audit
3
+ module Enum
4
+ module Technology
5
+ NODE: String
6
+ RUBY: String
7
+
8
+ def self.all: -> Array[String]
9
+ end
10
+ end
11
+ end
12
+ end
@@ -3,17 +3,19 @@ module Package
3
3
  class Package
4
4
  @groups: Array[Symbol]
5
5
  @risks: Array[Risk]
6
+ @technology: String
6
7
  @vulnerabilities: Array[String]
7
8
 
8
9
  attr_accessor groups: Array[Symbol]
9
10
  attr_accessor latest_version: String
10
11
  attr_accessor latest_version_date: String
11
12
  attr_reader name: String
13
+ attr_reader technology: String
12
14
  attr_reader version: String
13
15
  attr_accessor version_date: String
14
16
  attr_accessor vulnerabilities: Array[String]
15
17
 
16
- def initialize: (String, String, **untyped) -> void
18
+ def initialize: (String, String, String, **untyped) -> void
17
19
 
18
20
  def deprecated?: -> bool
19
21
 
@@ -4,7 +4,7 @@ module Package
4
4
  attr_reader explanation: String?
5
5
  attr_reader type: String
6
6
 
7
- def initialize: (String, ?String?)-> void
7
+ def initialize: (String, ?String?) -> void
8
8
 
9
9
  def <=>: (Risk) -> Integer?
10
10
  end
@@ -2,18 +2,17 @@ module Package
2
2
  module Audit
3
3
  module Npm
4
4
  class NodeCollection
5
- PACKAGE_JSON: String
6
- PACKAGE_LOCK: String
7
- YARN_LOCK: String
8
-
9
5
  @dir: String
6
+ @report: Symbol
10
7
 
11
- def initialize: (String) -> void
8
+ def initialize: (String, Symbol) -> void
12
9
 
13
10
  def all: -> Array[Package]
14
11
 
15
12
  def deprecated: -> Array[Package]
16
13
 
14
+ def fetch: -> Array[Package]
15
+
17
16
  def outdated: -> Array[Package]
18
17
 
19
18
  def vulnerable: -> Array[Package]
@@ -14,7 +14,7 @@ module Package
14
14
 
15
15
  private
16
16
 
17
- def update_meta_data: (Hash[Symbol, untyped])-> void
17
+ def update_meta_data: (Hash[Symbol, untyped]) -> void
18
18
  end
19
19
  end
20
20
  end
@@ -3,13 +3,16 @@ module Package
3
3
  module Ruby
4
4
  class GemCollection
5
5
  @dir: String
6
+ @report: Symbol
6
7
 
7
- def initialize: (String) -> void
8
+ def initialize: (String, Symbol) -> void
8
9
 
9
10
  def all: -> Array[Package]
10
11
 
11
12
  def deprecated: -> Array[Package]
12
13
 
14
+ def fetch: -> Array[Package]
15
+
13
16
  def outdated: (?include_implicit: bool) -> Array[Package]
14
17
 
15
18
  def vulnerable: -> Array[Package]
@@ -0,0 +1,31 @@
1
+ module Package
2
+ module Audit
3
+ class CommandParser
4
+ @config: Hash[String, untyped]?
5
+ @dir: String
6
+ @options: Hash[String, untyped]
7
+ @report: Symbol
8
+ @technologies: Array[String]
9
+
10
+ def initialize: (String, Hash[String, untyped], Symbol) -> void
11
+
12
+ def run: -> bool
13
+
14
+ private
15
+
16
+ def learn_more_command: (String) -> String?
17
+
18
+ def parse_config_file: -> Hash[String, untyped]?
19
+
20
+ def parse_technologies: -> Array[String]
21
+
22
+ def print_disclaimer: (String) -> void
23
+
24
+ def print_results: (String, Array[Package], Array[Package]) -> void
25
+
26
+ def print_summary: (String, Array[Package], Array[Package]) -> void
27
+
28
+ def report_fields: -> Array[Symbol]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Package
2
+ module Audit
3
+ class PackageFilter
4
+ @config: Hash[String, untyped]?
5
+
6
+ def initialize: (Hash[String, untyped]?) -> void
7
+
8
+ def ignored?: (Package) -> bool
9
+
10
+ private
11
+
12
+ def ignore_package?: (Package, Hash[String, untyped]?) -> bool
13
+
14
+ def pkg_version_in_config?: (Package, Hash[String, untyped]?) -> bool
15
+
16
+ def pkg_yaml_from_config: (Package) -> Hash[String, untyped]?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module Package
2
+ module Audit
3
+ class PackageFinder
4
+ @config: Hash[String, untyped]?
5
+ @dir: String
6
+ @report: Symbol
7
+
8
+ def initialize: (Hash[String, untyped]?, String, Symbol) -> void
9
+
10
+ def run: (String) -> Array[Array[Package]]
11
+
12
+ private
13
+
14
+ def filter_pkgs_based_on_config: (Array[Package]) -> Array[Package]
15
+
16
+ def find_by_technology: (String) -> Array[Package]
17
+
18
+ def find_node: -> Array[Package]
19
+
20
+ def find_ruby: -> Array[Package]
21
+ end
22
+ end
23
+ end
@@ -1,14 +1,14 @@
1
1
  module Package
2
2
  module Audit
3
- class Printer
3
+ class PackagePrinter
4
4
  BASH_FORMATTING_REGEX: Regexp
5
5
  COLUMN_GAP: Integer
6
6
  CSV_HEADERS: Hash[Symbol, String]
7
7
 
8
8
  @pkgs: Array[Package]
9
- @options: Hash[Symbol, untyped]
9
+ @options: Hash[String, untyped]
10
10
 
11
- def initialize: (Array[Package], Hash[Symbol, untyped]) -> void
11
+ def initialize: (Hash[String, untyped], Array[Package]) -> void
12
12
 
13
13
  def print: (Array[Symbol]) -> void
14
14
 
@@ -0,0 +1,19 @@
1
+ module Package
2
+ module Audit
3
+ module Technology
4
+ class Detector
5
+ @dir: String
6
+
7
+ def initialize: (String) -> void
8
+
9
+ def detect: -> Array[String]
10
+
11
+ private
12
+
13
+ def node?: -> bool
14
+
15
+ def ruby?: -> bool
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Package
2
+ module Audit
3
+ module Technology
4
+ class Validator
5
+ @dir: String
6
+
7
+ def initialize: (String) -> void
8
+
9
+ def validate!: (String) -> void
10
+
11
+ private
12
+
13
+ def validate_node!: -> void
14
+
15
+ def validate_ruby!: -> void
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,17 +2,17 @@ module Package
2
2
  module Audit
3
3
  module Util
4
4
  module SummaryPrinter
5
- def self.deprecated: -> void
5
+ def self.all: -> void
6
6
 
7
- def self.report: -> void
7
+ def self.deprecated: -> void
8
8
 
9
9
  def self.risk: -> void
10
10
 
11
- def self.statistics: (String, Array[Package]) -> void
11
+ def self.statistics: (String, Symbol, Array[Package], Array[Package]) -> void
12
12
 
13
- def self.total: (String, Array[Package]) -> void
13
+ def self.total: (String, Symbol, Array[Package], Array[Package]) -> void
14
14
 
15
- def self.vulnerable: (String, String) -> void
15
+ def self.vulnerable: (String, String?) -> void
16
16
  end
17
17
  end
18
18
  end