From 445b4449ab15d618c68242f700f0e27be6c42f37 Mon Sep 17 00:00:00 2001 From: Manabu Niseki Date: Sat, 8 Sep 2018 06:52:46 +0900 Subject: [PATCH] feat: add discover command --- lib/ryo/cli.rb | 37 +++++++++++++++++++++++++++++++------ lib/ryo/error.rb | 6 +++++- spec/cli_spec.rb | 19 +++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/lib/ryo/cli.rb b/lib/ryo/cli.rb index 2eb95e9..925c3a8 100644 --- a/lib/ryo/cli.rb +++ b/lib/ryo/cli.rb @@ -4,37 +4,62 @@ module Ryo class CLI < Thor desc "dir URL", "Discover directories and files belong to a given URL" def dir(url) - hash = discover(url, dir: true) + hash = run_discovery(url, dir: true) puts hash.to_json end desc "subdomain URL", "Discover subdomains of a given URL" def subdomain(url) - hash = discover(url, subdomain: true) + hash = run_discovery(url, subdomain: true) puts hash.to_json end desc "tech URL", "Discover used technolgies of a given URL" def tech(url) - hash = discover(url, tech: true) + hash = run_discovery(url, tech: true) puts hash.to_json end desc "whois URL", "Discover whois information of a given URL" def whois(url) - hash = discover(url, whois: true) + hash = run_discovery(url, whois: true) + puts hash.to_json + end + + desc "discover URL", "Run discovery plugin(s) against a given URL" + method_option :dir, type: :boolean, default: false + method_option :subdomain, type: :boolean, default: false + method_option :tech, type: :boolean, default: false + method_option :whois, type: :boolean, default: false + def discovery(url) + hash = run_discovery(url, options) puts hash.to_json end desc "all URL", "Run all discovery plugins against a given URL" def all(url) - hash = discover(url, all: true) + hash = run_discovery(url, all: true) puts hash.to_json end no_commands do - def discover(url, options) + def validate_url(url) + uri = URI.parse(url) + raise InvalidURLError unless %w(http https).include?(uri.scheme) + end + + def validate_options(options) + raise InvalidOptionsError unless options.any? { |_, v| v } + end + + def run_discovery(url, options) + validate_url(url) + validate_options(options) Ryo.discover url, options + rescue InvalidURLError => _ + { error: "Please input a valid URL" } + rescue InvalidOptionsError => _ + { error: "Please input at least one option" } rescue StandardError => e { error: "Warning: #{e}" } end diff --git a/lib/ryo/error.rb b/lib/ryo/error.rb index 25f0a49..cdd0bf6 100644 --- a/lib/ryo/error.rb +++ b/lib/ryo/error.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true + module Ryo class NotFoundError < StandardError; end -end \ No newline at end of file + class InvalidURLError < StandardError; end + class InvalidOptionsError < StandardError; end +end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 8ff026d..73617f0 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -42,6 +42,25 @@ expect(json).to be_a(Hash) end end + describe "#discover" do + context "when given an empty options" do + it "should return a JSON with an error message" do + output = capture(:stdout) { subject.start %w(discover http://localhost) } + json = JSON.parse(output) + expect(json["error"]).to eq("Please input at least one option") + end + end + context "when given valid options" do + before { + allow(Ryo::Plugin::Whois).to receive(:discover).and_return({}) + } + it "should return a JSON" do + output = capture(:stdout) { subject.start %w(discover http://localhost --whois) } + json = JSON.parse(output) + expect(json).to be_a(Hash) + end + end + end describe "#all" do before { allow(Ryo::Plugin::Dir).to receive(:discover).and_return({})