diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fd6916..0c08b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## Version 2.1.1 - YesWeHack Inactive Programs + +### 🐛 Bug Fixes + +- Exclude YesWeHack programs marked `archived` or `disabled` from synchronization, using both the program listing and detail response. +- Remove previously stored scopes for these programs on the next sync, so they no longer appear in `/`. The removal is recorded in history as a `remove_program` event. +- Update the CLI `version` command and HTTP User-Agent to report the current release. + +--- + ## Version 2.1.0 - Generic HTTP Webhook Notifications ### ✨ Features diff --git a/config/settings.yml b/config/settings.yml index c6e58cc..bbd168d 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -7,7 +7,7 @@ app: # HTTP client configuration http: - user_agent: "ScopesExtractor/2.0 (Ruby; +github.com/JoshuaMart/ScopesExtractor)" + user_agent: "ScopesExtractor/2.1.1 (Ruby; +github.com/JoshuaMart/ScopesExtractor)" proxy: null # Optional: "http://proxy.example.com:8080" timeout: 30 # seconds diff --git a/lib/scopes_extractor/cli.rb b/lib/scopes_extractor/cli.rb index 18833ca..855fe0f 100644 --- a/lib/scopes_extractor/cli.rb +++ b/lib/scopes_extractor/cli.rb @@ -10,7 +10,7 @@ def self.exit_on_failure? desc 'version', 'Display version information' def version - puts 'ScopesExtractor version 2.0.0' + puts 'ScopesExtractor version 2.1.1' end desc 'reset', 'Reset the database (WARNING: deletes all data)' diff --git a/lib/scopes_extractor/config.rb b/lib/scopes_extractor/config.rb index c0f5ac6..34caa35 100644 --- a/lib/scopes_extractor/config.rb +++ b/lib/scopes_extractor/config.rb @@ -29,7 +29,7 @@ def http end def user_agent - http[:user_agent] || 'ScopesExtractor/2.0' + http[:user_agent] || 'ScopesExtractor/2.1.1' end def proxy diff --git a/lib/scopes_extractor/platforms/yeswehack/platform.rb b/lib/scopes_extractor/platforms/yeswehack/platform.rb index 455c0c6..e9c5ec7 100644 --- a/lib/scopes_extractor/platforms/yeswehack/platform.rb +++ b/lib/scopes_extractor/platforms/yeswehack/platform.rb @@ -67,22 +67,17 @@ def fetch_programs fetcher = ProgramFetcher.new(@token) raw_programs = fetcher.fetch_all - # Filter out VDP programs before fetching details - if Config.skip_vdp?('yeswehack') - raw_programs = raw_programs.reject do |raw| - if raw['vdp'] == true - ScopesExtractor.logger.debug "[YesWeHack] Skipping VDP program: #{raw['slug']}" - true - else - false - end - end + # Inactive programs must disappear from the fetched set so the sync + # removes their previously stored scopes as well. + raw_programs = raw_programs.reject do |raw| + skip_program?(raw) end raw_programs.filter_map do |raw| # Fetch full details to get scopes details = fetcher.fetch_details(raw['slug']) next unless details + next if skip_program?(details) begin parse_program(details) @@ -97,6 +92,20 @@ def fetch_programs private + def skip_program?(data) + reason = if data['archived'] == true + 'archived' + elsif data['disabled'] == true + 'disabled' + elsif Config.skip_vdp?('yeswehack') && data['vdp'] == true + 'VDP' + end + return false unless reason + + ScopesExtractor.logger.debug "[YesWeHack] Skipping #{reason} program: #{data['slug']}" + true + end + def authenticate return @token if @token diff --git a/spec/scopes_extractor/config_spec.rb b/spec/scopes_extractor/config_spec.rb index 11a76b4..336bdee 100644 --- a/spec/scopes_extractor/config_spec.rb +++ b/spec/scopes_extractor/config_spec.rb @@ -36,7 +36,7 @@ describe 'http settings' do describe '.user_agent' do it 'returns the configured user agent' do - expect(described_class.user_agent).to include('ScopesExtractor/2.0') + expect(described_class.user_agent).to include('ScopesExtractor/2.1.1') expect(described_class.user_agent).to include('Ruby') expect(described_class.user_agent).to include('github.com') end diff --git a/spec/scopes_extractor/platforms/yeswehack/platform_spec.rb b/spec/scopes_extractor/platforms/yeswehack/platform_spec.rb index 307d04d..90a5b04 100644 --- a/spec/scopes_extractor/platforms/yeswehack/platform_spec.rb +++ b/spec/scopes_extractor/platforms/yeswehack/platform_spec.rb @@ -121,6 +121,31 @@ expect(platform.fetch_programs).to eq([]) end + %w[archived disabled].each do |status| + it "skips #{status} programs before fetching their details" do + allow(program_fetcher).to receive(:fetch_all).and_return( + [{ 'slug' => 'inactive', status => true }, + { 'slug' => 'active', 'archived' => false, 'disabled' => false }] + ) + allow(program_fetcher).to receive(:fetch_details).with('active').and_return( + 'slug' => 'active', 'title' => 'Active', 'bounty' => true, 'scopes' => [] + ) + + expect(program_fetcher).not_to receive(:fetch_details).with('inactive') + expect(platform.fetch_programs.map(&:slug)).to eq(['active']) + end + + it "skips a program whose details mark it #{status}" do + allow(program_fetcher).to receive(:fetch_all).and_return([{ 'slug' => 'inactive' }]) + allow(program_fetcher).to receive(:fetch_details).with('inactive').and_return( + 'slug' => 'inactive', 'title' => 'Inactive', 'bounty' => true, + 'scopes' => [], status => true + ) + + expect(platform.fetch_programs).to eq([]) + end + end + context 'when already authenticated' do it 'does not authenticate again' do # First call authenticates