diff options
author | Adam Wanninger <ajwann@ajwann.codes> | 2017-10-29 12:24:09 -0400 |
---|---|---|
committer | Adam Wanninger <ajwann@ajwann.codes> | 2018-01-25 10:00:58 -0500 |
commit | 40911ddadbd052e342ebb99ad4188efffc8290c1 (patch) | |
tree | b3431a3f022821ae821d136b6cc587f0e427a9aa | |
parent | 914a4a8b8d0cf1a79dbc7b334fbb5c2db1ecdc16 (diff) | |
download | bundler-40911ddadbd052e342ebb99ad4188efffc8290c1.tar.gz |
check Bundler.home permissions in doctor command
-rw-r--r-- | lib/bundler/cli/doctor.rb | 34 | ||||
-rw-r--r-- | spec/commands/doctor_spec.rb | 55 |
2 files changed, 74 insertions, 15 deletions
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb index 7f28a5eb13..93366c33a9 100644 --- a/lib/bundler/cli/doctor.rb +++ b/lib/bundler/cli/doctor.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "rbconfig" +require "find" module Bundler class CLI::Doctor @@ -61,6 +62,7 @@ module Bundler end def run + check_home_permissions Bundler.ui.level = "error" if options[:quiet] Bundler.settings.validate! check! @@ -90,5 +92,37 @@ module Bundler Bundler.ui.info "No issues found with the installed bundle" end end + + private + + def check_home_permissions + check_for_files_not_owned_by_current_user_but_still_rw + check_for_files_not_readable_or_writable + end + + def check_for_files_not_owned_by_current_user_but_still_rw + return unless any_files_not_owned_by_current_user_but_still_rw? + Bundler.ui.warn "Files exist in Bundler home that are owned by another " \ + "user, but are stil readable/writable" + end + + def check_for_files_not_readable_or_writable + return unless any_files_not_readable_or_writable? + raise ProductionError, "Files exist in Bundler home that are not " \ + "readable/writable to the current user" + end + + def any_files_not_readable_or_writable? + Find.find(Bundler.home.to_s).any? do |f| + !(File.writable?(f) && File.readable?(f)) + end + end + + def any_files_not_owned_by_current_user_but_still_rw? + Find.find(Bundler.home.to_s).any? do |f| + (File.stat(f).uid != Process.uid) && + (File.writable?(f) && File.readable?(f)) + end + end end end diff --git a/spec/commands/doctor_spec.rb b/spec/commands/doctor_spec.rb index 2572d4ff4d..3e58adff36 100644 --- a/spec/commands/doctor_spec.rb +++ b/spec/commands/doctor_spec.rb @@ -6,6 +6,19 @@ require "bundler/cli/doctor" RSpec.describe "bundle doctor" do before(:each) do + install_gemfile! <<-G + source "file://#{gem_repo1}" + gem "rack" + G + + stat = double("stat") + unwritable_file = double("file") + allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] } + allow(File).to receive(:stat).with(unwritable_file) { stat } + allow(stat).to receive(:uid) { Process.uid } + allow(File).to receive(:writable?).with(unwritable_file) { true } + allow(File).to receive(:readable?).with(unwritable_file) { true } + @stdout = StringIO.new [:error, :warn].each do |method| @@ -17,21 +30,11 @@ RSpec.describe "bundle doctor" do end it "exits with no message if the installed gem has no C extensions" do - install_gemfile! <<-G - source "file://#{gem_repo1}" - gem "rack" - G - expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error expect(@stdout.string).to be_empty end it "exits with no message if the installed gem's C extension dylib breakage is fine" do - install_gemfile! <<-G - source "file://#{gem_repo1}" - gem "rack" - G - doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"] @@ -42,11 +45,6 @@ RSpec.describe "bundle doctor" do end it "exits with a message if one of the linked libraries is missing" do - install_gemfile! <<-G - source "file://#{gem_repo1}" - gem "rack" - G - doctor = Bundler::CLI::Doctor.new({}) expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"] @@ -58,4 +56,31 @@ RSpec.describe "bundle doctor" do * rack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib E end + + it "exits with an error if home contains files that are not read/write" do + stat = double("stat") + unwritable_file = double("file") + doctor = Bundler::CLI::Doctor.new({}) + allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] } + allow(File).to receive(:stat).with(unwritable_file) { stat } + allow(stat).to receive(:uid) { Process.uid } + allow(File).to receive(:writable?).with(unwritable_file) { false } + allow(File).to receive(:readable?).with(unwritable_file) { false } + expect { doctor.run }.to raise_error( + Bundler::ProductionError, + "Files exist in Bundler home that are not readable/writable to the current user" + ) + end + + it "exits with a warning if home contains files that are read/write but not owned by current user" do + stat = double("stat") + unwritable_file = double("file") + allow(Find).to receive(:find).with(Bundler.home.to_s) { [unwritable_file] } + allow(File).to receive(:stat).with(unwritable_file) { stat } + allow(stat).to receive(:uid) { 0o0000 } + allow(File).to receive(:writable?).with(unwritable_file) { true } + allow(File).to receive(:readable?).with(unwritable_file) { true } + expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error + expect(@stdout.string).to include("Files exist in Bundler home that are owned by another user, but are stil readable/writable") + end end |