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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b01c3c377fec4245b836119f812bbacc6ceac724ed3c64da348f0b97481fd2a1
4
- data.tar.gz: ceec2dc5e451fbe9ece1b915e35f790ed2ef60efb18fb3130ccc876e1eb7237c
3
+ metadata.gz: d30d08ba36373c75427371f922cb0a5819a021868bf82001428e0541571df9f8
4
+ data.tar.gz: ac4dce54e3905dd56de9b137a62101de7267262c1f6b0310e4697c8f016a36b8
5
5
  SHA512:
6
- metadata.gz: '0438ecb657dcaf116dc0048b89a9de474785d88e868f68f306521e917045651b525f49c8a6b802fda8401e8ff795f02b79c0be627fd337dc5eff4dcd48eaf128'
7
- data.tar.gz: 38f68c6e7251196f2a526d4affcbb1487760615dd6947a3bd11b20f6ed0f791bac762a1327741b7c31e72ffa6a6b44471fdcfa98c0e0135d5d77b1751729ce80
6
+ metadata.gz: 00be4151f4f124614d117a739a558f9f2816f0f72095f222ddadf5101a6d089b40bdc5369c4a68c9b096b1547932561394f1fee5ca58712e13a4909c4a8c9558
7
+ data.tar.gz: f224c2c2fe2ff39586d20989ef6999d7b2a52acd2276dcdd9895441105ccaebc5991523676b88545a5afa96d4ffcac10291ab76dfab735b65d42aabc4598d7e4
@@ -1,11 +1,8 @@
1
+ require_relative 'const/file'
1
2
  require_relative 'const/time'
3
+ require_relative 'enum/option'
4
+ require_relative 'services/command_parser'
2
5
  require_relative 'version'
3
- require_relative 'util/summary_printer'
4
- require_relative 'ruby/bundler_specs'
5
- require_relative 'printer'
6
- require_relative 'ruby/gem_collection'
7
- require_relative 'npm/node_collection'
8
- require_relative 'command_service'
9
6
 
10
7
  require 'json'
11
8
  require 'thor'
@@ -15,57 +12,52 @@ module Package
15
12
  class CLI < Thor
16
13
  default_task :report
17
14
 
15
+ class_option Enum::Option::CONFIG,
16
+ aliases: '-c', banner: 'FILE',
17
+ desc: "Path to a custom configuration file, default: #{Const::File::CONFIG})"
18
+ class_option Enum::Option::TECHNOLOGY,
19
+ aliases: '-t', repeatable: true,
20
+ desc: 'Technology to be audited (repeat this flag for each technology)'
21
+ class_option Enum::Option::INCLUDE_IGNORED,
22
+ type: :boolean, default: false,
23
+ desc: 'Include packages ignored by a configuration file'
24
+ class_option Enum::Option::CSV,
25
+ type: :boolean, default: false,
26
+ desc: 'Output reports using comma separated values (CSV)'
27
+ class_option Enum::Option::CSV_EXCLUDE_HEADERS,
28
+ type: :boolean, default: false,
29
+ desc: "Hide headers when using the --#{Enum::Option::CSV} option"
30
+
31
+ map '-v' => :version
18
32
  map '--version' => :version
19
33
 
20
34
  desc 'report [DIR]', 'Show a report of potentially deprecated, outdated or vulnerable packages'
21
- method_option :csv, type: :boolean, default: false, desc: 'Output using comma separated values (CSV)'
22
- method_option :'exclude-headers', type: :boolean, default: false, desc: 'Hide headers if when using CSV'
23
-
24
35
  def report(dir = Dir.pwd)
25
- # within_rescue_block do
26
- exit CommandService.new(dir, options).all
27
- # end
36
+ within_rescue_block { exit CommandParser.new(dir, options, Enum::Report::ALL).run }
28
37
  end
29
38
 
30
39
  desc 'deprecated [DIR]',
31
40
  "Show packages with no updates by author for at least #{Const::Time::YEARS_ELAPSED_TO_BE_OUTDATED} years"
32
- method_option :csv, type: :boolean, default: false, desc: 'Output using comma separated values (CSV)'
33
- method_option :'exclude-headers', type: :boolean, default: false, desc: 'Hide headers if when using CSV'
34
-
35
41
  def deprecated(dir = Dir.pwd)
36
- within_rescue_block do
37
- exit CommandService.new(dir, options).deprecated
38
- end
42
+ within_rescue_block { exit CommandParser.new(dir, options, Enum::Report::DEPRECATED).run }
39
43
  end
40
44
 
41
45
  desc 'outdated [DIR]', 'Show packages that are out of date'
42
- method_option :csv, type: :boolean, default: false, desc: 'Output using comma separated values (CSV)'
43
- method_option :'exclude-headers', type: :boolean, default: false, desc: 'Hide headers if when using CSV'
44
-
45
46
  def outdated(dir = Dir.pwd)
46
- within_rescue_block do
47
- exit CommandService.new(dir, options).outdated
48
- end
47
+ within_rescue_block { exit CommandParser.new(dir, options, Enum::Report::OUTDATED).run }
49
48
  end
50
49
 
51
50
  desc 'vulnerable [DIR]', 'Show packages and their dependencies that have security vulnerabilities'
52
- method_option :csv, type: :boolean, default: false, desc: 'Output using comma separated values (CSV)'
53
- method_option :'exclude-headers', type: :boolean, default: false, desc: 'Hide headers if when using CSV'
54
-
55
51
  def vulnerable(dir = Dir.pwd)
56
- within_rescue_block do
57
- exit CommandService.new(dir, options).vulnerable
58
- end
52
+ within_rescue_block { exit CommandParser.new(dir, options, Enum::Report::VULNERABLE).run }
59
53
  end
60
54
 
61
55
  desc 'risk', 'Print information on how risk is calculated'
62
-
63
56
  def risk
64
57
  Util::SummaryPrinter.risk
65
58
  end
66
59
 
67
60
  desc 'version', 'Print the currently installed version of the package-audit gem'
68
-
69
61
  def version
70
62
  puts "package-audit #{VERSION}"
71
63
  end
@@ -74,6 +66,14 @@ module Package
74
66
  true
75
67
  end
76
68
 
69
+ def method_missing(command, *args)
70
+ invoke :report, [command], args
71
+ end
72
+
73
+ def respond_to_missing?
74
+ true
75
+ end
76
+
77
77
  private
78
78
 
79
79
  def within_rescue_block
@@ -2,7 +2,7 @@ module Package
2
2
  module Audit
3
3
  module Const
4
4
  module Fields
5
- ALL = %i[
5
+ AVAILABLE = %i[
6
6
  name
7
7
  version
8
8
  version_date
@@ -14,15 +14,15 @@ module Package
14
14
  risk_explanation
15
15
  ]
16
16
 
17
- REPORT = %i[name version latest_version latest_version_date groups vulnerabilities risk_type risk_explanation]
18
- VULNERABLE = %i[name version latest_version groups vulnerabilities]
17
+ ALL = %i[name version latest_version latest_version_date groups vulnerabilities risk_type risk_explanation]
18
+ DEPRECATED = %i[name version latest_version latest_version_date groups]
19
19
  OUTDATED = %i[name version latest_version latest_version_date groups]
20
+ VULNERABLE = %i[name version latest_version groups vulnerabilities]
20
21
 
21
22
  # the names of these fields must match the instance variables in the Dependency class
22
23
  HEADERS = {
23
24
  name: 'Package',
24
25
  version: 'Version',
25
- version_date: 'Date',
26
26
  latest_version: 'Latest',
27
27
  latest_version_date: 'Latest Date',
28
28
  groups: 'Groups',
@@ -2,6 +2,7 @@ module Package
2
2
  module Audit
3
3
  module Const
4
4
  module File
5
+ CONFIG = '.package-audit.yml'
5
6
  GEMFILE = 'Gemfile'
6
7
  GEMFILE_LOCK = 'Gemfile.lock'
7
8
  PACKAGE_JSON = 'package.json'
@@ -0,0 +1,13 @@
1
+ module Package
2
+ module Audit
3
+ module Const
4
+ module YAML
5
+ DEPRECATED = 'deprecated'
6
+ OUTDATED = 'outdated'
7
+ VULNERABLE = 'vulnerable'
8
+ TECHNOLOGY = 'technology'
9
+ VERSION = 'version'
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 = 'config'
6
+ CSV = 'csv'
7
+ CSV_EXCLUDE_HEADERS = 'exclude-headers'
8
+ INCLUDE_IGNORED = 'include-ignored'
9
+ TECHNOLOGY = 'technology'
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 = :all
6
+ DEPRECATED = :deprecated
7
+ OUTDATED = :outdated
8
+ VULNERABLE = :vulnerable
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module Package
2
+ module Audit
3
+ module Enum
4
+ module Technology
5
+ NODE = 'node'
6
+ RUBY = 'ruby'
7
+
8
+ def self.all
9
+ constants.map { |key| Enum::Technology.const_get(key) }.sort
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
- require_relative 'base'
2
1
  require_relative '../util/bash_color'
2
+ require_relative 'base'
3
3
 
4
4
  module Package
5
5
  module Audit
@@ -1,5 +1,5 @@
1
- require_relative 'base'
2
1
  require_relative '../util/bash_color'
2
+ require_relative 'base'
3
3
 
4
4
  module Package
5
5
  module Audit
@@ -1,6 +1,6 @@
1
- require_relative 'base'
2
1
  require_relative '../const/time'
3
2
  require_relative '../util/bash_color'
3
+ require_relative 'base'
4
4
 
5
5
  require 'time'
6
6
 
@@ -1,6 +1,6 @@
1
- require_relative 'base'
2
1
  require_relative '../enum/vulnerability_type'
3
2
  require_relative '../util/bash_color'
3
+ require_relative 'base'
4
4
 
5
5
  module Package
6
6
  module Audit
@@ -1,18 +1,19 @@
1
+ require_relative '../enum/environment'
2
+ require_relative '../enum/risk_explanation'
3
+ require_relative '../enum/risk_type'
4
+ require_relative '../services/risk_calculator'
1
5
  require_relative 'risk'
2
- require_relative 'risk_calculator'
3
- require_relative 'enum/environment'
4
- require_relative 'enum/risk_type'
5
- require_relative 'enum/risk_explanation'
6
6
 
7
7
  module Package
8
8
  module Audit
9
9
  class Package
10
- attr_reader :name, :version
10
+ attr_reader :name, :version, :technology
11
11
  attr_accessor :groups, :version_date, :latest_version, :latest_version_date, :vulnerabilities
12
12
 
13
- def initialize(name, version, **attr)
13
+ def initialize(name, version, technology, **attr)
14
14
  @name = name.to_s
15
15
  @version = version.to_s
16
+ @technology = technology.to_s
16
17
  @groups = []
17
18
  @vulnerabilities = []
18
19
  @risks = []
@@ -1,18 +1,29 @@
1
- require_relative 'yarn_lock_parser'
1
+ require_relative '../const/file'
2
+ require_relative '../services/duplicate_package_merger'
2
3
  require_relative 'npm_meta_data'
3
4
  require_relative 'vulnerability_finder'
4
- require_relative '../duplicate_package_merger'
5
+ require_relative 'yarn_lock_parser'
5
6
 
6
7
  module Package
7
8
  module Audit
8
9
  module Npm
9
10
  class NodeCollection
10
- PACKAGE_JSON = 'package.json'
11
- PACKAGE_LOCK = 'package-lock.json'
12
- YARN_LOCK = 'yarn.lock'
13
-
14
- def initialize(dir)
11
+ def initialize(dir, report)
15
12
  @dir = dir
13
+ @report = report
14
+ end
15
+
16
+ def fetch
17
+ case @report
18
+ when Enum::Report::DEPRECATED
19
+ deprecated
20
+ when Enum::Report::OUTDATED
21
+ outdated
22
+ when Enum::Report::VULNERABLE
23
+ vulnerable
24
+ else
25
+ all
26
+ end
16
27
  end
17
28
 
18
29
  def all
@@ -44,7 +55,7 @@ module Package
44
55
  private
45
56
 
46
57
  def fetch_from_package_json
47
- package_json = JSON.parse(File.read("#{@dir}/#{PACKAGE_JSON}"), symbolize_names: true)
58
+ package_json = JSON.parse(File.read("#{@dir}/#{Const::File::PACKAGE_JSON}"), symbolize_names: true)
48
59
  default_deps = package_json[:dependencies] || {}
49
60
  dev_deps = package_json[:devDependencies] || {}
50
61
  [default_deps, dev_deps]
@@ -52,8 +63,8 @@ module Package
52
63
 
53
64
  def fetch_from_lock_file
54
65
  default_deps, dev_deps = fetch_from_package_json
55
- if File.exist?("#{@dir}/#{YARN_LOCK}")
56
- YarnLockParser.new("#{@dir}/#{YARN_LOCK}").fetch(default_deps || {}, dev_deps || {})
66
+ if File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
67
+ YarnLockParser.new("#{@dir}/#{Const::File::YARN_LOCK}").fetch(default_deps || {}, dev_deps || {})
57
68
  else
58
69
  []
59
70
  end
@@ -34,7 +34,7 @@ module Package
34
34
  full_name = "#{name}@#{version}"
35
35
  vulnerability = advisory[:severity] || Enum::VulnerabilityType::UNKNOWN
36
36
 
37
- @vuln_hash[full_name] = Package.new(name, version) unless @vuln_hash.key? full_name
37
+ @vuln_hash[full_name] = Package.new(name, version, 'node') unless @vuln_hash.key? full_name
38
38
  @vuln_hash[full_name].update vulnerabilities: @vuln_hash[full_name].vulnerabilities + [vulnerability]
39
39
  @vuln_hash[full_name].update groups: @pkg_hash[parent_name].groups
40
40
  end
@@ -12,7 +12,7 @@ module Package
12
12
  default_deps.merge(dev_deps).each do |dep_name, expected_version|
13
13
  pkg_block = fetch_package_block(dep_name, expected_version)
14
14
  version = fetch_package_version(dep_name, pkg_block)
15
- pks = Package.new(dep_name.to_s, version)
15
+ pks = Package.new(dep_name.to_s, version, 'node')
16
16
  pks.update groups: dev_deps.key?(dep_name) ? %i[development] : %i[default development]
17
17
  pkgs << pks
18
18
  end
@@ -1,4 +1,4 @@
1
- require_relative '../package'
1
+ require_relative '../models/package'
2
2
  require_relative 'gem_meta_data'
3
3
  require_relative 'vulnerability_finder'
4
4
 
@@ -1,18 +1,35 @@
1
- require_relative 'bundler_specs'
1
+ require_relative '../enum/report'
2
2
  require_relative '../enum/risk_type'
3
- require_relative '../duplicate_package_merger'
3
+ require_relative '../services/duplicate_package_merger'
4
+ require_relative 'bundler_specs'
4
5
 
5
6
  module Package
6
7
  module Audit
7
8
  module Ruby
8
9
  class GemCollection
9
- def initialize(dir)
10
+ def initialize(dir, report)
10
11
  @dir = dir
12
+ @report = report
11
13
  end
12
14
 
15
+ def fetch
16
+ case @report
17
+ when Enum::Report::DEPRECATED
18
+ deprecated
19
+ when Enum::Report::OUTDATED
20
+ outdated
21
+ when Enum::Report::VULNERABLE
22
+ vulnerable
23
+ else
24
+ all
25
+ end
26
+ end
27
+
28
+ private
29
+
13
30
  def all
14
31
  specs = BundlerSpecs.gemfile(@dir)
15
- pkgs = specs.map { |spec| Package.new(spec.name, spec.version) }
32
+ pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
16
33
  vulnerable_pkgs = VulnerabilityFinder.new(@dir).run
17
34
  pkgs = GemMetaData.new(pkgs + vulnerable_pkgs).fetch.filter(&:risk?)
18
35
  DuplicatePackageMerger.new(pkgs).run
@@ -20,14 +37,14 @@ module Package
20
37
 
21
38
  def deprecated
22
39
  specs = BundlerSpecs.gemfile(@dir)
23
- pkgs = specs.map { |spec| Package.new(spec.name, spec.version) }
40
+ pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
24
41
  pkgs = GemMetaData.new(pkgs).fetch.filter(&:deprecated?)
25
42
  DuplicatePackageMerger.new(pkgs).run
26
43
  end
27
44
 
28
45
  def outdated(include_implicit: false)
29
46
  specs = include_implicit ? BundlerSpecs.all(@dir) : BundlerSpecs.gemfile(@dir)
30
- pkgs = specs.map { |spec| Package.new(spec.name, spec.version) }
47
+ pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
31
48
  pkgs = GemMetaData.new(pkgs).fetch.filter(&:outdated?)
32
49
  DuplicatePackageMerger.new(pkgs).run
33
50
  end
@@ -1,4 +1,4 @@
1
- require_relative '../package'
1
+ require_relative '../models/package'
2
2
 
3
3
  module Package
4
4
  module Audit
@@ -26,7 +26,7 @@ module Package
26
26
  version = json[:gem][:version]
27
27
  full_name = "#{name}@#{version}"
28
28
  vulnerability = json[:advisory][:criticality] || Enum::VulnerabilityType::UNKNOWN
29
- @vuln_hash[full_name] = Package.new(name, version) unless @vuln_hash.key? full_name
29
+ @vuln_hash[full_name] = Package.new(name, version, 'ruby') unless @vuln_hash.key? full_name
30
30
  @vuln_hash[full_name].update vulnerabilities: @vuln_hash[full_name].vulnerabilities + [vulnerability]
31
31
  end
32
32
  end
@@ -0,0 +1,103 @@
1
+ require_relative '../const/cmd'
2
+ require_relative '../const/file'
3
+ require_relative '../enum/option'
4
+ require_relative '../enum/report'
5
+ require_relative '../technology/detector'
6
+ require_relative '../technology/validator'
7
+ require_relative '../util/summary_printer'
8
+ require_relative 'package_finder'
9
+ require_relative 'package_printer'
10
+
11
+ require 'yaml'
12
+
13
+ module Package
14
+ module Audit
15
+ class CommandParser
16
+ def initialize(dir, options, report)
17
+ @dir = dir
18
+ @options = options
19
+ @report = report
20
+ @config = parse_config_file
21
+ @technologies = parse_technologies
22
+ end
23
+
24
+ def run
25
+ cumulative_pkgs = []
26
+
27
+ @technologies.each do |technology|
28
+ all_pkgs, ignored_pkgs = PackageFinder.new(@config, @dir, @report).run(technology)
29
+ ignored_pkgs = [] if @options[Enum::Option::INCLUDE_IGNORED]
30
+ cumulative_pkgs << all_pkgs
31
+ print_results(technology, (all_pkgs || []) - (ignored_pkgs || []), ignored_pkgs || [])
32
+ end
33
+
34
+ cumulative_pkgs.any?
35
+ end
36
+
37
+ private
38
+
39
+ def print_results(technology, pkgs, ignored_pkgs)
40
+ PackagePrinter.new(@options, pkgs).print(report_fields)
41
+ print_summary(technology, pkgs, ignored_pkgs) unless @options[Enum::Option::CSV]
42
+ print_disclaimer(technology) unless @options[Enum::Option::CSV] || pkgs.empty?
43
+ end
44
+
45
+ def print_summary(technology, pkgs, ignored_pkgs)
46
+ if @report == Enum::Report::ALL
47
+ Util::SummaryPrinter.statistics(technology, @report, pkgs, ignored_pkgs)
48
+ else
49
+ Util::SummaryPrinter.total(technology, @report, pkgs, ignored_pkgs)
50
+ end
51
+ end
52
+
53
+ def print_disclaimer(technology)
54
+ case @report
55
+ when Enum::Report::DEPRECATED
56
+ Util::SummaryPrinter.deprecated
57
+ when Enum::Report::ALL, Enum::Report::VULNERABLE
58
+ Util::SummaryPrinter.vulnerable(technology, learn_more_command(technology))
59
+ end
60
+ end
61
+
62
+ def learn_more_command(technology)
63
+ case technology
64
+ when Enum::Technology::RUBY
65
+ Const::Cmd::BUNDLE_AUDIT
66
+ when Enum::Technology::NODE
67
+ Const::Cmd::YARN_AUDIT
68
+ else
69
+ raise ArgumentError, "Unexpected technology \"#{technology}\" found in #{__method__}"
70
+ end
71
+ end
72
+
73
+ def report_fields
74
+ case @report
75
+ when Enum::Report::DEPRECATED
76
+ Const::Fields::DEPRECATED
77
+ when Enum::Report::OUTDATED
78
+ Const::Fields::OUTDATED
79
+ when Enum::Report::VULNERABLE
80
+ Const::Fields::VULNERABLE
81
+ else
82
+ Const::Fields::ALL
83
+ end
84
+ end
85
+
86
+ def parse_config_file
87
+ if @options[Enum::Option::CONFIG].nil?
88
+ YAML.load_file("#{@dir}/#{Const::File::CONFIG}") if File.exist? "#{@dir}/#{Const::File::CONFIG}"
89
+ elsif File.exist? @options[Enum::Option::CONFIG]
90
+ YAML.load_file(@options[Enum::Option::CONFIG])
91
+ else
92
+ raise ArgumentError, "Configuration file not found: #{@options[Enum::Option::CONFIG]}"
93
+ end
94
+ end
95
+
96
+ def parse_technologies
97
+ technology_validator = Technology::Validator.new(@dir)
98
+ @options[Enum::Option::TECHNOLOGY]&.each { |technology| technology_validator.validate! technology }
99
+ @options[Enum::Option::TECHNOLOGY] || Technology::Detector.new(@dir).detect
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../const/cmd'
2
+ require_relative '../const/file'
3
+ require_relative '../const/yaml'
4
+ require_relative '../enum/technology'
5
+ require_relative '../ruby/gem_collection'
6
+
7
+ require 'yaml'
8
+
9
+ module Package
10
+ module Audit
11
+ class PackageFilter
12
+ def initialize(config)
13
+ @config = config
14
+ end
15
+
16
+ def ignored?(pkg)
17
+ pkg_yaml = pkg_yaml_from_config(pkg)
18
+ pkg_version_in_config?(pkg, pkg_yaml) && ignore_package?(pkg, pkg_yaml)
19
+ end
20
+
21
+ private
22
+
23
+ def pkg_yaml_from_config(pkg)
24
+ yaml_fragment = @config&.dig(Const::YAML::TECHNOLOGY, pkg.technology, pkg.name)&.to_yaml
25
+ yaml_fragment.nil? ? nil : YAML.safe_load(yaml_fragment)
26
+ end
27
+
28
+ def pkg_version_in_config?(pkg, yaml)
29
+ yaml&.dig(Const::YAML::VERSION) == pkg.version
30
+ end
31
+
32
+ def ignore_package?(pkg, yaml)
33
+ (!pkg.deprecated? || yaml&.dig(Const::YAML::DEPRECATED) == false) &&
34
+ (!pkg.outdated? || yaml&.dig(Const::YAML::OUTDATED) == false) &&
35
+ (!pkg.vulnerable? || yaml&.dig(Const::YAML::VULNERABLE) == false)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../const/cmd'
2
+ require_relative '../const/file'
3
+ require_relative '../const/yaml'
4
+ require_relative '../enum/technology'
5
+ require_relative '../npm/node_collection'
6
+ require_relative '../ruby/gem_collection'
7
+ require_relative 'package_filter'
8
+
9
+ require 'yaml'
10
+
11
+ module Package
12
+ module Audit
13
+ class PackageFinder
14
+ def initialize(config, dir, report)
15
+ @config = config
16
+ @dir = dir
17
+ @report = report
18
+ end
19
+
20
+ def run(technology)
21
+ all_pkgs = find_by_technology(technology)
22
+ ignored_pkgs = filter_pkgs_based_on_config(all_pkgs)
23
+ [all_pkgs, ignored_pkgs]
24
+ end
25
+
26
+ private
27
+
28
+ def find_by_technology(technology)
29
+ case technology
30
+ when Enum::Technology::RUBY
31
+ find_ruby
32
+ when Enum::Technology::NODE
33
+ find_node
34
+ else
35
+ []
36
+ end
37
+ end
38
+
39
+ def find_node
40
+ Npm::NodeCollection.new(@dir, @report).fetch
41
+ end
42
+
43
+ def find_ruby
44
+ Ruby::GemCollection.new(@dir, @report).fetch
45
+ end
46
+
47
+ def filter_pkgs_based_on_config(pkgs)
48
+ package_filter = PackageFilter.new(@config)
49
+ ignored_pkgs = []
50
+
51
+ pkgs.each do |pkg|
52
+ ignored_pkgs << pkg if package_filter.ignored?(pkg)
53
+ end
54
+ ignored_pkgs
55
+ end
56
+ end
57
+ end
58
+ end