diff --git a/spec/beef/core/api/registrar_spec.rb b/spec/beef/core/api/registrar_spec.rb deleted file mode 100644 index 1036cfe73..000000000 --- a/spec/beef/core/api/registrar_spec.rb +++ /dev/null @@ -1,219 +0,0 @@ -RSpec.describe BeEF::API::Registrar do - let(:registrar) { described_class.instance } - let(:test_owner) { Class.new } - let(:test_api_class) do - api_class = Class.new - api_class.const_set(:API_PATHS, { 'test_method' => :test_method }.freeze) - # Make it appear to be under BeEF::API namespace for fire method - allow(api_class).to receive(:ancestors).and_return([BeEF::API::Module]) - api_class - end - - before do - # Reset singleton state - registrar.instance_variable_set(:@registry, []) - registrar.instance_variable_set(:@count, 1) - end - - describe '#initialize' do - it 'initializes with empty registry and count of 1' do - expect(registrar.instance_variable_get(:@registry)).to eq([]) - expect(registrar.instance_variable_get(:@count)).to eq(1) - end - end - - describe '#register' do - it 'registers an API hook' do - id = registrar.register(test_owner, test_api_class, 'test_method') - expect(id).to eq(1) - expect(registrar.instance_variable_get(:@registry).length).to eq(1) - end - - it 'returns nil when API path does not exist' do - invalid_class = Class.new - result = registrar.register(test_owner, invalid_class, 'nonexistent') - expect(result).to be_nil - expect(registrar.instance_variable_get(:@registry)).to be_empty - end - - it 'returns nil when already registered' do - registrar.register(test_owner, test_api_class, 'test_method') - result = registrar.register(test_owner, test_api_class, 'test_method') - expect(result).to be_nil - expect(registrar.instance_variable_get(:@registry).length).to eq(1) - end - - it 'increments count for each registration' do - id1 = registrar.register(test_owner, test_api_class, 'test_method') - other_owner = Class.new - id2 = registrar.register(other_owner, test_api_class, 'test_method') - expect(id1).to eq(1) - expect(id2).to eq(2) - end - - it 'accepts params array' do - id = registrar.register(test_owner, test_api_class, 'test_method', ['param1']) - expect(id).to eq(1) - registry = registrar.instance_variable_get(:@registry) - expect(registry[0]['params']).to eq(['param1']) - end - end - - describe '#registered?' do - it 'returns true when registered' do - registrar.register(test_owner, test_api_class, 'test_method') - expect(registrar.registered?(test_owner, test_api_class, 'test_method')).to be true - end - - it 'returns false when not registered' do - expect(registrar.registered?(test_owner, test_api_class, 'test_method')).to be false - end - - it 'matches params when checking registration' do - registrar.register(test_owner, test_api_class, 'test_method', ['param1']) - expect(registrar.registered?(test_owner, test_api_class, 'test_method', ['param1'])).to be true - expect(registrar.registered?(test_owner, test_api_class, 'test_method', ['param2'])).to be false - end - end - - describe '#matched?' do - it 'returns true when a registration matches' do - registrar.register(test_owner, test_api_class, 'test_method') - expect(registrar.matched?(test_api_class, 'test_method')).to be true - end - - it 'returns false when no registration matches' do - expect(registrar.matched?(test_api_class, 'test_method')).to be false - end - end - - describe '#unregister' do - it 'removes registration by id' do - id = registrar.register(test_owner, test_api_class, 'test_method') - registrar.unregister(id) - expect(registrar.instance_variable_get(:@registry)).to be_empty - end - end - - describe '#get_owners' do - it 'returns owners for a registered API hook' do - id = registrar.register(test_owner, test_api_class, 'test_method') - owners = registrar.get_owners(test_api_class, 'test_method') - expect(owners.length).to eq(1) - expect(owners[0][:owner]).to eq(test_owner) - expect(owners[0][:id]).to eq(id) - end - - it 'returns empty array when no owners registered' do - owners = registrar.get_owners(test_api_class, 'test_method') - expect(owners).to eq([]) - end - end - - describe '#verify_api_path' do - it 'returns true for valid API path' do - expect(registrar.verify_api_path(test_api_class, 'test_method')).to be true - end - - it 'returns false for invalid API path' do - expect(registrar.verify_api_path(test_api_class, 'nonexistent')).to be false - end - - it 'returns false for class without API_PATHS constant' do - invalid_class = Class.new - # Remove API_PATHS if it exists from previous tests - invalid_class.send(:remove_const, :API_PATHS) if invalid_class.const_defined?(:API_PATHS) - expect(registrar.verify_api_path(invalid_class, 'test_method')).to be false - end - end - - describe '#get_api_path' do - it 'returns symbol for valid API path' do - expect(registrar.get_api_path(test_api_class, 'test_method')).to eq(:test_method) - end - - it 'returns nil for invalid API path' do - expect(registrar.get_api_path(test_api_class, 'nonexistent')).to be_nil - end - end - - describe '#is_matched_params?' do - it 'returns true when params match' do - reg = { 'params' => ['param1', 'param2'] } # rubocop:disable Style/WordArray - expect(registrar.is_matched_params?(reg, ['param1', 'param2'])).to be true # rubocop:disable Style/WordArray - end - - it 'returns false when params do not match' do - reg = { 'params' => ['param1'] } - expect(registrar.is_matched_params?(reg, ['param2'])).to be false - end - - it 'returns true when stored params include nil' do - reg = { 'params' => ['param1', nil] } - expect(registrar.is_matched_params?(reg, ['param1', 'anything'])).to be true # rubocop:disable Style/WordArray - end - - it 'returns true when lengths do not match (early return)' do - reg = { 'params' => ['param1'] } - expect(registrar.is_matched_params?(reg, ['param1', 'param2'])).to be true # rubocop:disable Style/WordArray - end - - it 'returns true when stored params is empty' do - reg = { 'params' => [] } - expect(registrar.is_matched_params?(reg, [])).to be true - end - end - - describe '#fire' do - let(:mock_owner_class) do - Class.new do - def self.test_method(arg) - "result_#{arg}" - end - end - end - - it 'fires registered API hooks' do - registrar.register(mock_owner_class, test_api_class, 'test_method') - result = registrar.fire(test_api_class, 'test_method', 'test_arg') - expect(result.length).to eq(1) - expect(result[0][:data]).to eq('result_test_arg') - end - - it 'returns nil when no owners registered' do - result = registrar.fire(test_api_class, 'test_method') - expect(result).to be_nil - end - - it 'returns empty array when API path not defined but class is registered' do - # Create a class that passes registration but fails verify_api_path in fire - invalid_class = Class.new - invalid_class.const_set(:API_PATHS, { 'test_method' => :test_method }.freeze) - allow(invalid_class).to receive(:ancestors).and_return([Class.new]) # Not under BeEF::API - registrar.register(mock_owner_class, invalid_class, 'test_method') - result = registrar.fire(invalid_class, 'test_method') - expect(result).to eq([]) - end - - it 'handles errors gracefully' do - error_owner_class = Class.new do - def self.test_method - raise StandardError, 'Test error' - end - end - registrar.register(error_owner_class, test_api_class, 'test_method') - expect { registrar.fire(test_api_class, 'test_method') }.not_to raise_error - end - - it 'skips nil results' do - nil_owner_class = Class.new do - def self.test_method - nil - end - end - registrar.register(nil_owner_class, test_api_class, 'test_method') - result = registrar.fire(test_api_class, 'test_method') - expect(result).to eq([]) - end - end -end diff --git a/spec/beef/core/main/crypto_spec.rb b/spec/beef/core/main/crypto_spec.rb index c29ed8e54..bfe4ccfbf 100644 --- a/spec/beef/core/main/crypto_spec.rb +++ b/spec/beef/core/main/crypto_spec.rb @@ -33,21 +33,6 @@ RSpec.describe 'BeEF::Core::Crypto' do end end - describe '.api_token' do - it 'generates a 40-character hex token and stores it in config' do - token = BeEF::Core::Crypto.api_token - expect(token).to be_a(String) - expect(token.length).to eq(40) # 20 bytes = 40 hex chars - expect(config.get('beef.api_token')).to eq(token) - end - - it 'generates different tokens on each call' do - token1 = BeEF::Core::Crypto.api_token - token2 = BeEF::Core::Crypto.api_token - expect(token1).not_to eq(token2) - end - end - describe '.random_alphanum_string' do it 'generates a string of the specified length' do result = BeEF::Core::Crypto.random_alphanum_string(15) diff --git a/spec/beef/core/main/rest/api_spec.rb b/spec/beef/core/main/rest/api_spec.rb deleted file mode 100644 index fd91a5e7e..000000000 --- a/spec/beef/core/main/rest/api_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -RSpec.describe BeEF::Core::Rest do - describe '.permitted_source?' do - it 'returns false for invalid IP' do - expect(BeEF::Core::Rest.permitted_source?('invalid')).to be false - end - - it 'returns false when permitted_ui_subnet is nil' do - allow(BeEF::Core::Configuration.instance).to receive(:get).with('beef.restrictions.permitted_ui_subnet').and_return(nil) - expect(BeEF::Core::Rest.permitted_source?('127.0.0.1')).to be false - end - - it 'returns false when permitted_ui_subnet is empty' do - allow(BeEF::Core::Configuration.instance).to receive(:get).with('beef.restrictions.permitted_ui_subnet').and_return([]) - expect(BeEF::Core::Rest.permitted_source?('127.0.0.1')).to be false - end - - it 'returns true when IP is in permitted subnet' do - allow(BeEF::Core::Configuration.instance).to receive(:get).with('beef.restrictions.permitted_ui_subnet').and_return(['127.0.0.0/8']) - expect(BeEF::Core::Rest.permitted_source?('127.0.0.1')).to be true - end - - it 'returns false when IP is not in permitted subnet' do - allow(BeEF::Core::Configuration.instance).to receive(:get).with('beef.restrictions.permitted_ui_subnet').and_return(['192.168.0.0/24']) - expect(BeEF::Core::Rest.permitted_source?('127.0.0.1')).to be false - end - end - - describe '.timeout?' do - let(:config) { BeEF::Core::Configuration.instance } - - it 'returns true when enough time has passed' do - allow(config).to receive(:get).with('beef.restrictions.api_attempt_delay').and_return(1) - last_time = Time.now - 2 - time_setter = ->(_time) {} - expect(BeEF::Core::Rest.timeout?('beef.restrictions.api_attempt_delay', last_time, time_setter)).to be true - end - - it 'returns false when not enough time has passed' do - allow(config).to receive(:get).with('beef.restrictions.api_attempt_delay').and_return(5) - last_time = Time.now - 1 - time_set = nil - time_setter = ->(time) { time_set = time } - result = BeEF::Core::Rest.timeout?('beef.restrictions.api_attempt_delay', last_time, time_setter) - expect(result).to be false - expect(time_set).not_to be_nil - end - end -end diff --git a/spec/beef/core/main/rest/handlers/browserdetails_spec.rb b/spec/beef/core/main/rest/handlers/browserdetails_spec.rb deleted file mode 100644 index ac9c60e92..000000000 --- a/spec/beef/core/main/rest/handlers/browserdetails_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -RSpec.describe BeEF::Core::Rest::BrowserDetails do - let(:config) { BeEF::Core::Configuration.instance } - let(:api_token) { 'test_token' } - - before do - allow(config).to receive(:get).and_call_original - allow(config).to receive(:get).with('beef.api_token').and_return(api_token) - allow(BeEF::Core::Rest).to receive(:permitted_source?).and_return(true) - end - - describe 'GET /:session' do - it 'returns browser details for a session' do - hb = BeEF::Core::Models::HookedBrowser.create!(session: 'test_session', ip: '127.0.0.1') - BeEF::Core::Models::BrowserDetails.create!(session_id: hb.session, detail_key: 'browser.name', detail_value: 'Chrome') - BeEF::Core::Models::BrowserDetails.create!(session_id: hb.session, detail_key: 'browser.version', detail_value: '91.0') - - # Test the logic directly - details = BeEF::Core::Models::BrowserDetails.where(session_id: hb.session) - result = details.map { |d| { key: d.detail_key, value: d.detail_value } } - - output = { - 'count' => result.length, - 'details' => result - } - - parsed = JSON.parse(output.to_json) - expect(parsed['count']).to eq(2) - expect(parsed['details'].length).to eq(2) - expect(parsed['details'][0]['key']).to eq('browser.name') - expect(parsed['details'][0]['value']).to eq('Chrome') - end - - it 'handles session with no browser details' do - hb = BeEF::Core::Models::HookedBrowser.create!(session: 'empty_session', ip: '127.0.0.1') - - details = BeEF::Core::Models::BrowserDetails.where(session_id: hb.session) - result = details.map { |d| { key: d.detail_key, value: d.detail_value } } - - output = { - 'count' => result.length, - 'details' => result - } - - parsed = JSON.parse(output.to_json) - expect(parsed['count']).to eq(0) - expect(parsed['details']).to eq([]) - end - end -end diff --git a/spec/beef/core/main/rest/handlers/categories_spec.rb b/spec/beef/core/main/rest/handlers/categories_spec.rb deleted file mode 100644 index e6dc6cff5..000000000 --- a/spec/beef/core/main/rest/handlers/categories_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -RSpec.describe BeEF::Core::Rest::Categories do - let(:config) { BeEF::Core::Configuration.instance } - let(:api_token) { 'test_token' } - - before do - allow(config).to receive(:get).and_call_original - allow(config).to receive(:get).with('beef.api_token').and_return(api_token) - allow(BeEF::Core::Rest).to receive(:permitted_source?).and_return(true) - end - - describe 'GET /' do - it 'returns categories as JSON' do - allow(BeEF::Modules).to receive(:get_categories).and_return(['Browser', 'Network']) # rubocop:disable Style/WordArray - - # Test the logic directly - categories = BeEF::Modules.get_categories - cats = [] - i = 0 - categories.each do |category| - cat = { 'id' => i, 'name' => category } - cats << cat - i += 1 - end - result = cats.to_json - - parsed = JSON.parse(result) - expect(parsed.length).to eq(2) - expect(parsed[0]['id']).to eq(0) - expect(parsed[0]['name']).to eq('Browser') - expect(parsed[1]['id']).to eq(1) - expect(parsed[1]['name']).to eq('Network') - end - - it 'handles empty categories' do - allow(BeEF::Modules).to receive(:get_categories).and_return([]) - - categories = BeEF::Modules.get_categories - cats = [] - i = 0 - categories.each do |category| - cat = { 'id' => i, 'name' => category } - cats << cat - i += 1 - end - result = cats.to_json - - parsed = JSON.parse(result) - expect(parsed).to eq([]) - end - end -end diff --git a/spec/beef/core/main/rest/handlers/logs_spec.rb b/spec/beef/core/main/rest/handlers/logs_spec.rb deleted file mode 100644 index 31535920f..000000000 --- a/spec/beef/core/main/rest/handlers/logs_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ -RSpec.describe BeEF::Core::Rest::Logs do - let(:config) { BeEF::Core::Configuration.instance } - let(:api_token) { 'test_token' } - - before do - allow(config).to receive(:get).and_call_original - allow(config).to receive(:get).with('beef.api_token').and_return(api_token) - allow(BeEF::Core::Rest).to receive(:permitted_source?).and_return(true) - end - - describe 'logs_to_json helper method' do - it 'converts logs to JSON format' do - hb = BeEF::Core::Models::HookedBrowser.create!(session: 'test_session', ip: '127.0.0.1') - BeEF::Core::Models::Log.create!( - event: 'Test Event 1', - logtype: 'INFO', - hooked_browser_id: hb.id, - date: Time.now - ) - BeEF::Core::Models::Log.create!( - event: 'Test Event 2', - logtype: 'WARN', - hooked_browser_id: hb.id, - date: Time.now - ) - - logs = BeEF::Core::Models::Log.all - - # Test the logic directly - logs_json = logs.map do |log| - { - 'id' => log.id.to_i, - 'date' => log.date.to_s, - 'event' => log.event.to_s, - 'logtype' => log.logtype.to_s, - 'hooked_browser_id' => log.hooked_browser_id.to_s - } - end - count = logs.length - - result = unless logs_json.empty? - { - 'logs_count' => count, - 'logs' => logs_json - }.to_json - end - - parsed = JSON.parse(result) - expect(parsed['logs_count']).to eq(2) - expect(parsed['logs'].length).to eq(2) - expect(parsed['logs'][0]['event']).to eq('Test Event 1') - expect(parsed['logs'][0]['logtype']).to eq('INFO') - end - - it 'handles empty logs' do - logs = BeEF::Core::Models::Log.all - - logs_json = logs.map do |log| - { - 'id' => log.id.to_i, - 'date' => log.date.to_s, - 'event' => log.event.to_s, - 'logtype' => log.logtype.to_s, - 'hooked_browser_id' => log.hooked_browser_id.to_s - } - end - count = logs.length - - result = unless logs_json.empty? - { - 'logs_count' => count, - 'logs' => logs_json - }.to_json - end - - expect(result).to be_nil - end - end - - describe 'GET /:session' do - it 'returns logs for a specific session' do - hb = BeEF::Core::Models::HookedBrowser.create!(session: 'test_session', ip: '127.0.0.1') - BeEF::Core::Models::Log.create!( - event: 'Session Event', - logtype: 'INFO', - hooked_browser_id: hb.id, - date: Time.now - ) - - logs = BeEF::Core::Models::Log.where(hooked_browser_id: hb.id) - expect(logs.length).to eq(1) - expect(logs.first.event).to eq('Session Event') - end - end -end