oauth 0.5.1 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/README.rdoc +22 -9
  3. data/bin/oauth +8 -2
  4. data/lib/oauth.rb +3 -2
  5. data/lib/oauth/cli.rb +37 -359
  6. data/lib/oauth/cli/authorize_command.rb +71 -0
  7. data/lib/oauth/cli/base_command.rb +208 -0
  8. data/lib/oauth/cli/help_command.rb +22 -0
  9. data/lib/oauth/cli/query_command.rb +25 -0
  10. data/lib/oauth/cli/sign_command.rb +81 -0
  11. data/lib/oauth/cli/version_command.rb +7 -0
  12. data/lib/oauth/client/action_controller_request.rb +1 -1
  13. data/lib/oauth/client/em_http.rb +0 -1
  14. data/lib/oauth/client/helper.rb +8 -2
  15. data/lib/oauth/client/net_http.rb +0 -1
  16. data/lib/oauth/consumer.rb +70 -14
  17. data/lib/oauth/helper.rb +10 -6
  18. data/lib/oauth/request_proxy/action_controller_request.rb +6 -2
  19. data/lib/oauth/request_proxy/action_dispatch_request.rb +7 -0
  20. data/lib/oauth/request_proxy/base.rb +5 -1
  21. data/lib/oauth/signature/hmac/sha256.rb +17 -0
  22. data/lib/oauth/tokens/request_token.rb +10 -3
  23. data/lib/oauth/version.rb +1 -1
  24. metadata +88 -72
  25. data/lib/oauth/core_ext.rb +0 -31
  26. data/test/cases/oauth_case.rb +0 -19
  27. data/test/cases/spec/1_0-final/test_construct_request_url.rb +0 -62
  28. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +0 -88
  29. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +0 -86
  30. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +0 -77
  31. data/test/integration/consumer_test.rb +0 -307
  32. data/test/test_access_token.rb +0 -26
  33. data/test/test_action_controller_request_proxy.rb +0 -157
  34. data/test/test_consumer.rb +0 -226
  35. data/test/test_curb_request_proxy.rb +0 -77
  36. data/test/test_em_http_client.rb +0 -80
  37. data/test/test_em_http_request_proxy.rb +0 -115
  38. data/test/test_helper.rb +0 -33
  39. data/test/test_hmac_sha1.rb +0 -20
  40. data/test/test_net_http_client.rb +0 -302
  41. data/test/test_net_http_request_proxy.rb +0 -72
  42. data/test/test_oauth_helper.rb +0 -94
  43. data/test/test_rack_request_proxy.rb +0 -40
  44. data/test/test_request_token.rb +0 -56
  45. data/test/test_rest_client_request_proxy.rb +0 -81
  46. data/test/test_rsa_sha1.rb +0 -59
  47. data/test/test_server.rb +0 -41
  48. data/test/test_signature.rb +0 -15
  49. data/test/test_signature_base.rb +0 -32
  50. data/test/test_signature_hmac_sha1.rb +0 -40
  51. data/test/test_signature_plain_text.rb +0 -31
  52. data/test/test_token.rb +0 -14
  53. data/test/test_typhoeus_request_proxy.rb +0 -101
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4e52bba31bed6b4a6bb18b934ce067a3e5a5f9c0
4
- data.tar.gz: 0c64d7eec3f2ff1e1d257b9762b93fe30512032b
2
+ SHA256:
3
+ metadata.gz: 9bd785e08f2a318da373f07b79fe6583ed3e8c26bcc92c5e1513ee615ea0f037
4
+ data.tar.gz: 3e9f81feb37166f4fec398d20e8b4de882b6e1e2304f893c033b920ab737616a
5
5
  SHA512:
6
- metadata.gz: ab1329b4b6a666b9eb80b46337727beeb1b2825f3358fc9647e5dda57c3a1c3fe2f6e9a427f8672dca7ae36d11b6aabb6278891f56b6a13ff4fa2f26aee3d023
7
- data.tar.gz: 2c871f1404d9c02457ac3a08becf5a6e8e56c9e68f3a15b3bfbd9841a23a9f7d6ce2d808a921f68ffb51454861e990305998c430c3c197b2233e5fd17cc4d65d
6
+ metadata.gz: 6bc060045ecb7ca1c47263f4bab7fde62c3a173ccf7ea6e1dacc5ac4e814ecea88e4b2f594f6bd2a7d80f9393e1295b1a5cbc85f3eb74c35cbb348da6f32cfe6
7
+ data.tar.gz: c96c9abd68f71cca8d33db21e3d68f1c7fe98898dba924fd440bf882280d99d39beb7a0751be913bb0f18872875ca8098792733f1717ff8d127156a99a69f039
data/README.rdoc CHANGED
@@ -1,5 +1,11 @@
1
1
  = Ruby OAuth
2
2
 
3
+ == Status
4
+
5
+ {<img src="https://travis-ci.org/oauth-xx/oauth-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.com/github/oauth-xx/oauth-ruby]
6
+
7
+
8
+
3
9
  == What
4
10
 
5
11
  This is a RubyGem for implementing both OAuth clients and servers in Ruby applications.
@@ -16,31 +22,38 @@ The source code is now hosted on the OAuth GitHub Project http://github.com/oaut
16
22
 
17
23
  This is a ruby library which is intended to be used in creating Ruby Consumer and Service Provider applications. It is NOT a Rails plugin, but could easily be used for the foundation for such a Rails plugin.
18
24
 
19
- As a matter of fact it has been pulled out from an OAuth Rails Plugin http://code.google.com/p/oauth-plugin/ which now requires this GEM.
25
+ As a matter of fact it has been pulled out from an OAuth Rails GEM (https://rubygems.org/gems/oauth-plugin https://github.com/pelle/oauth-plugin) which now uses this gem as a dependency.
20
26
 
21
27
  == Demonstration of usage
22
28
 
23
29
  We need to specify the oauth_callback url explicitly, otherwise it defaults to "oob" (Out of Band)
24
30
 
25
- @callback_url = "http://127.0.0.1:3000/oauth/callback"
31
+ callback_url = "http://127.0.0.1:3000/oauth/callback"
26
32
 
27
- Create a new consumer instance by passing it a configuration hash:
33
+ Create a new `OAuth::Consumer` instance by passing it a configuration hash:
28
34
 
29
- @consumer = OAuth::Consumer.new("key","secret", :site => "https://agree2")
35
+ oauth_consumer = OAuth::Consumer.new("key", "secret", :site => "https://agree2")
30
36
 
31
37
  Start the process by requesting a token
32
38
 
33
- @request_token = @consumer.get_request_token(:oauth_callback => @callback_url)
34
- session[:request_token] = @request_token
35
- redirect_to @request_token.authorize_url(:oauth_callback => @callback_url)
39
+ request_token = oauth_consumer.get_request_token(:oauth_callback => callback_url)
40
+
41
+ session[:token] = request_token.token
42
+ session[:token_secret] = request_token.secret
43
+ redirect_to request_token.authorize_url(:oauth_callback => callback_url)
36
44
 
37
45
  When user returns create an access_token
38
46
 
39
- @access_token = @request_token.get_access_token
40
- @photos = @access_token.get('/photos.xml')
47
+ hash = { oauth_token: session[:token], oauth_token_secret: session[:token_secret]}
48
+ request_token = OAuth::RequestToken.from_hash(oauth_consumer, hash)
49
+ access_token = request_token.get_access_token
50
+ # For 3-legged authorization, flow oauth_verifier is passed as param in callback
51
+ # access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
52
+ @photos = access_token.get('/photos.xml')
41
53
 
42
54
  Now that you have an access token, you can use Typhoeus to interact with the OAuth provider if you choose.
43
55
 
56
+ require 'typhoeus'
44
57
  require 'oauth/request_proxy/typhoeus_request'
45
58
  oauth_params = {:consumer => oauth_consumer, :token => access_token}
46
59
  hydra = Typhoeus::Hydra.new
data/bin/oauth CHANGED
@@ -1,5 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "oauth/cli"
3
+ require_relative "../lib/oauth"
4
+ require 'oauth/cli'
4
5
 
5
- OAuth::CLI.execute(STDOUT, STDIN, STDERR, ARGV)
6
+ Signal.trap("INT") { puts; exit(1) } # don't dump a backtrace on a ^C
7
+
8
+ ARGV << 'help' if ARGV.empty?
9
+ command = ARGV.shift
10
+
11
+ OAuth::CLI.new(STDOUT, STDIN, STDERR, command, ARGV).run
data/lib/oauth.rb CHANGED
@@ -1,11 +1,12 @@
1
- $LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
1
+ root = File.dirname(__FILE__)
2
+ $LOAD_PATH << root unless $LOAD_PATH.include?(root)
2
3
 
3
4
  require 'oauth/version'
4
5
 
5
6
  require 'oauth/oauth'
6
- require 'oauth/core_ext'
7
7
 
8
8
  require 'oauth/client/helper'
9
9
  require 'oauth/signature/hmac/sha1'
10
+ require 'oauth/signature/hmac/sha256'
10
11
  require 'oauth/signature/rsa/sha1'
11
12
  require 'oauth/request_proxy/mock_request'
data/lib/oauth/cli.rb CHANGED
@@ -1,378 +1,56 @@
1
1
  require 'optparse'
2
- require 'oauth'
2
+ require 'oauth/cli/base_command'
3
+ require 'oauth/cli/help_command'
4
+ require 'oauth/cli/query_command'
5
+ require 'oauth/cli/authorize_command'
6
+ require 'oauth/cli/sign_command'
7
+ require 'oauth/cli/version_command'
8
+ require 'active_support/core_ext/string/inflections'
3
9
 
4
10
  module OAuth
5
11
  class CLI
6
- SUPPORTED_COMMANDS = {
7
- "authorize" => "Obtain an access token and secret for a user",
8
- "debug" => "Verbosely generate an OAuth signature",
9
- "query" => "Query a protected resource",
10
- "sign" => "Generate an OAuth signature",
11
- "version" => "Display the current version of the library"
12
- }
13
-
14
- attr_reader :command
15
- attr_reader :options
16
- attr_reader :stdout, :stdin
17
-
18
- def self.execute(stdout, stdin, stderr, arguments = [])
19
- self.new.execute(stdout, stdin, stderr, arguments)
20
- end
21
-
22
- def initialize
23
- @options = {}
24
-
25
- # don't dump a backtrace on a ^C
26
- trap(:INT) {
27
- exit
28
- }
29
- end
30
-
31
- def execute(stdout, stdin, stderr, arguments = [])
32
- @stdout = stdout
33
- @stdin = stdin
34
- @stderr = stderr
35
- extract_command_and_parse_options(arguments)
36
-
37
- if sufficient_options? && valid_command?
38
- if command == "debug"
39
- @command = "sign"
40
- @options[:verbose] = true
41
- end
42
-
43
- case command
44
- # TODO move command logic elsewhere
45
- when "authorize"
46
- begin
47
- consumer = OAuth::Consumer.new \
48
- options[:oauth_consumer_key],
49
- options[:oauth_consumer_secret],
50
- :access_token_url => options[:access_token_url],
51
- :authorize_url => options[:authorize_url],
52
- :request_token_url => options[:request_token_url],
53
- :scheme => options[:scheme],
54
- :http_method => options[:method].to_s.downcase.to_sym
55
-
56
- # parameters for OAuth 1.0a
57
- oauth_verifier = nil
58
-
59
- # get a request token
60
- request_token = consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, options[:scope] ? { "scope" => options[:scope] } : {})
61
-
62
- if request_token.callback_confirmed?
63
- stdout.puts "Server appears to support OAuth 1.0a; enabling support."
64
- options[:version] = "1.0a"
65
- end
66
-
67
- stdout.puts "Please visit this url to authorize:"
68
- stdout.puts request_token.authorize_url
69
-
70
- if options[:version] == "1.0a"
71
- stdout.puts "Please enter the verification code provided by the SP (oauth_verifier):"
72
- oauth_verifier = stdin.gets.chomp
73
- else
74
- stdout.puts "Press return to continue..."
75
- stdin.gets
76
- end
77
-
78
- begin
79
- # get an access token
80
- access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
81
-
82
- stdout.puts "Response:"
83
- access_token.params.each do |k,v|
84
- stdout.puts " #{k}: #{v}" unless k.is_a?(Symbol)
85
- end
86
- rescue OAuth::Unauthorized => e
87
- stderr.puts "A problem occurred while attempting to obtain an access token:"
88
- stderr.puts e
89
- stderr.puts e.request.body
90
- end
91
- rescue OAuth::Unauthorized => e
92
- stderr.puts "A problem occurred while attempting to authorize:"
93
- stderr.puts e
94
- stderr.puts e.request.body
95
- end
96
- when "query"
97
- consumer = OAuth::Consumer.new \
98
- options[:oauth_consumer_key],
99
- options[:oauth_consumer_secret],
100
- :scheme => options[:scheme]
101
-
102
- access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
103
-
104
- # append params to the URL
105
- uri = URI.parse(options[:uri])
106
- params = prepare_parameters.map { |k,v| v.map { |v2| "#{URI.encode(k)}=#{URI.encode(v2)}" } * "&" }
107
- uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
108
- p uri.to_s
109
-
110
- response = access_token.request(options[:method].to_s.downcase.to_sym, uri.to_s)
111
- puts "#{response.code} #{response.message}"
112
- puts response.body
113
- when "sign"
114
- parameters = prepare_parameters
115
-
116
- request = OAuth::RequestProxy.proxy \
117
- "method" => options[:method],
118
- "uri" => options[:uri],
119
- "parameters" => parameters
120
-
121
- if verbose?
122
- stdout.puts "OAuth parameters:"
123
- request.oauth_parameters.each do |k,v|
124
- stdout.puts " " + [k, v] * ": "
125
- end
126
- stdout.puts
127
-
128
- if request.non_oauth_parameters.any?
129
- stdout.puts "Parameters:"
130
- request.non_oauth_parameters.each do |k,v|
131
- stdout.puts " " + [k, v] * ": "
132
- end
133
- stdout.puts
134
- end
135
- end
136
-
137
- request.sign! \
138
- :consumer_secret => options[:oauth_consumer_secret],
139
- :token_secret => options[:oauth_token_secret]
140
-
141
- if verbose?
142
- stdout.puts "Method: #{request.method}"
143
- stdout.puts "URI: #{request.uri}"
144
- stdout.puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
145
- stdout.puts "Signature base string: #{request.signature_base_string}"
146
-
147
- if options[:xmpp]
148
- stdout.puts
149
- stdout.puts "XMPP Stanza:"
150
- stdout.puts <<-EOS
151
- <oauth xmlns='urn:xmpp:oauth:0'>
152
- <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
153
- <oauth_token>#{request.oauth_token}</oauth_token>
154
- <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
155
- <oauth_signature>#{request.oauth_signature}</oauth_signature>
156
- <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
157
- <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
158
- <oauth_version>#{request.oauth_version}</oauth_version>
159
- </oauth>
160
- EOS
161
- stdout.puts
162
- stdout.puts "Note: You may want to use bare JIDs in your URI."
163
- stdout.puts
164
- else
165
- stdout.puts "OAuth Request URI: #{request.signed_uri}"
166
- stdout.puts "Request URI: #{request.signed_uri(false)}"
167
- stdout.puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
168
- end
169
- stdout.puts "Signature: #{request.oauth_signature}"
170
- stdout.puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
171
- else
172
- stdout.puts request.oauth_signature
173
- end
174
- when "version"
175
- puts "OAuth for Ruby #{OAuth::VERSION}"
176
- end
177
- else
178
- usage
179
- end
12
+ def self.puts_red(string)
13
+ puts "\033[0;91m#{string}\033[0m"
180
14
  end
181
15
 
182
- protected
183
-
184
- def extract_command_and_parse_options(arguments)
185
- @command = arguments[-1]
186
- parse_options(arguments[0..-1])
187
- end
188
-
189
- def option_parser(arguments = "")
190
- # TODO add realm parameter
191
- # TODO add user-agent parameter
192
- option_parser = OptionParser.new do |opts|
193
- opts.banner = "Usage: #{$0} [options] <command>"
194
-
195
- # defaults
196
- options[:oauth_nonce] = OAuth::Helper.generate_key
197
- options[:oauth_signature_method] = "HMAC-SHA1"
198
- options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
199
- options[:oauth_version] = "1.0"
200
- options[:method] = :post
201
- options[:params] = []
202
- options[:scheme] = :header
203
- options[:version] = "1.0"
204
-
205
- ## Common Options
206
-
207
- opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
208
- options[:scheme] = :body
209
- end
210
-
211
- opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
212
- options[:oauth_consumer_key] = v
213
- end
214
-
215
- opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
216
- options[:oauth_consumer_secret] = v
217
- end
218
-
219
- opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
220
- options[:scheme] = :header
221
- end
222
-
223
- opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
224
- options[:scheme] = :query_string
225
- end
226
-
227
- opts.on("-O", "--options FILE", "Read options from a file") do |v|
228
- arguments.unshift(*open(v).readlines.map { |l| l.chomp.split(" ") }.flatten)
229
- end
230
-
231
- ## Options for signing and making requests
232
-
233
- opts.separator("\n options for signing and querying")
234
-
235
- opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
236
- options[:method] = v
237
- end
238
-
239
- opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
240
- options[:oauth_nonce] = v
241
- end
242
-
243
- opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
244
- options[:params] << v
245
- end
246
-
247
- opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
248
- options[:oauth_signature_method] = v
249
- end
250
-
251
- opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
252
- options[:oauth_token_secret] = v
253
- end
254
-
255
- opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
256
- options[:oauth_timestamp] = v
257
- end
258
-
259
- opts.on("--token TOKEN", "Specifies the token to use.") do |v|
260
- options[:oauth_token] = v
261
- end
262
-
263
- opts.on("--realm REALM", "Specifies the realm to use.") do |v|
264
- options[:realm] = v
265
- end
266
-
267
- opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
268
- options[:uri] = v
269
- end
270
-
271
- opts.on("--version [VERSION]", "Specifies the OAuth version to use.") do |v|
272
- if v
273
- options[:oauth_version] = v
274
- else
275
- @command = "version"
276
- end
277
- end
278
-
279
- opts.on("--no-version", "Omit oauth_version.") do
280
- options[:oauth_version] = nil
281
- end
282
-
283
- opts.on("--xmpp", "Generate XMPP stanzas.") do
284
- options[:xmpp] = true
285
- options[:method] ||= "iq"
286
- end
287
-
288
- opts.on("-v", "--verbose", "Be verbose.") do
289
- options[:verbose] = true
290
- end
291
-
292
- ## Options for authorization
293
-
294
- opts.separator("\n options for authorization")
295
-
296
- opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
297
- options[:access_token_url] = v
298
- end
299
-
300
- opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
301
- options[:authorize_url] = v
302
- end
303
-
304
- opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
305
- options[:oauth_callback] = v
306
- end
307
-
308
- opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
309
- options[:request_token_url] = v
310
- end
16
+ ALIASES = {
17
+ 'h' => 'help',
18
+ 'v' => 'version',
19
+ 'q' => 'query',
20
+ 'a' => 'authorize',
21
+ 's' => 'sign',
22
+ }
311
23
 
312
- opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
313
- options[:scope] = v
314
- end
315
- end
24
+ def initialize(stdout, stdin, stderr, command, arguments)
25
+ klass = get_command_class(parse_command(command))
26
+ @command = klass.new(stdout, stdin, stderr, arguments)
27
+ @help_command = HelpCommand.new(stdout, stdin, stderr, [])
316
28
  end
317
29
 
318
- def parse_options(arguments)
319
- option_parser(arguments).parse!(arguments)
30
+ def run
31
+ @command.run
320
32
  end
321
33
 
322
- def prepare_parameters
323
- escaped_pairs = options[:params].collect do |pair|
324
- if pair =~ /:/
325
- Hash[*pair.split(":", 2)].collect do |k,v|
326
- [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
327
- end
328
- else
329
- pair
330
- end
331
- end
34
+ private
332
35
 
333
- querystring = escaped_pairs * "&"
334
- cli_params = CGI.parse(querystring)
335
-
336
- {
337
- "oauth_consumer_key" => options[:oauth_consumer_key],
338
- "oauth_nonce" => options[:oauth_nonce],
339
- "oauth_timestamp" => options[:oauth_timestamp],
340
- "oauth_token" => options[:oauth_token],
341
- "oauth_signature_method" => options[:oauth_signature_method],
342
- "oauth_version" => options[:oauth_version]
343
- }.reject { |k,v| v.nil? || v == "" }.merge(cli_params)
36
+ def get_command_class(command)
37
+ Object.const_get("OAuth::CLI::#{command.camelize}Command")
344
38
  end
345
39
 
346
- def sufficient_options?
347
- case command
348
- # TODO move command logic elsewhere
349
- when "authorize"
350
- options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
351
- options[:access_token_url] && options[:authorize_url] &&
352
- options[:request_token_url]
353
- when "version"
354
- true
40
+ def parse_command(command)
41
+ case command = command.to_s.downcase
42
+ when '--version', '-v'
43
+ 'version'
44
+ when '--help', '-h', nil, ''
45
+ 'help'
46
+ when *ALIASES.keys
47
+ ALIASES[command]
48
+ when *ALIASES.values
49
+ command
355
50
  else
356
- options[:oauth_consumer_key] && options[:oauth_consumer_secret] &&
357
- options[:method] && options[:uri]
358
- end
359
- end
360
-
361
- def usage
362
- stdout.puts option_parser.help
363
- stdout.puts
364
- stdout.puts "Available commands:"
365
- SUPPORTED_COMMANDS.each do |command, desc|
366
- puts " #{command.ljust(15)}#{desc}"
51
+ OAuth::CLI.puts_red "Command '#{command}' not found"
52
+ 'help'
367
53
  end
368
54
  end
369
-
370
- def valid_command?
371
- SUPPORTED_COMMANDS.keys.include?(command)
372
- end
373
-
374
- def verbose?
375
- options[:verbose]
376
- end
377
55
  end
378
56
  end