worochi 0.0.7 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/worochi/agent/{sample.rb → #example.rb} +2 -14
  3. data/lib/worochi/agent/dropbox.rb +3 -13
  4. data/lib/worochi/agent/github.rb +8 -23
  5. data/lib/worochi/agent.rb +46 -18
  6. data/lib/worochi/config/#example.yml +35 -0
  7. data/lib/worochi/config/dropbox.yml +14 -0
  8. data/lib/worochi/config/github.yml +17 -0
  9. data/lib/worochi/config.rb +9 -84
  10. data/lib/worochi/configurator.rb +120 -0
  11. data/lib/worochi/helper/github_helper.rb +111 -0
  12. data/lib/worochi/helper.rb +28 -7
  13. data/lib/worochi/item.rb +5 -3
  14. data/lib/worochi/log.rb +8 -14
  15. data/lib/worochi/oauth.rb +69 -0
  16. data/lib/worochi/version.rb +1 -1
  17. data/lib/worochi.rb +20 -3
  18. data/spec/cassettes/Worochi/_push/pushes_with_agents.yml +512 -0
  19. data/spec/cassettes/Worochi_Agent_Dropbox/_push_item/pushes_it_chunked_if_size_exceeds_limit.yml +1049 -0
  20. data/spec/cassettes/Worochi_Agent_Dropbox/_push_item_chunked/raises_an_error.yml +44 -0
  21. data/spec/cassettes/Worochi_Agent_Dropbox/_push_items/pushes_multiple_items.yml +165 -0
  22. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files/raises_error_on_invalid_path.yml +38 -0
  23. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing.yml +79 -0
  24. data/spec/cassettes/Worochi_Agent_Dropbox/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing_including_the_required_fields.yml +79 -0
  25. data/spec/cassettes/Worochi_Agent_Github/_list/works_with_absolute_paths.yml +12 -12
  26. data/spec/cassettes/Worochi_Agent_Github/_repos/lists_the_repos.yml +207 -0
  27. data/spec/cassettes/Worochi_Agent_Github/_source_branch/retrieves_the_master_branch_correctly.yml +6 -6
  28. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/accepts_a_different_relative_path.yml +12 -12
  29. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/contains_file1.yml +12 -12
  30. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/does_not_contain_folder1.yml +12 -12
  31. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files/raises_error_on_invalid_path.yml +133 -0
  32. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files_and_folders/contains_folder1_and_file1.yml +24 -24
  33. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_files_and_folders/shows_detailed_listing_including_the_required_fields.yml +133 -0
  34. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/accepts_a_different_relative_path.yml +12 -12
  35. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/contains_folder1.yml +12 -12
  36. data/spec/cassettes/Worochi_Agent_Github/it_should_behave_like_a_service_agent/_folders/does_not_contain_file1.yml +12 -12
  37. data/spec/cassettes/Worochi_Agent_Github/{_push_all → modifies_the_repo/_push_all}/pushes_a_list_of_items_to_create_a_new_commit.yml +80 -80
  38. data/spec/cassettes/Worochi_Agent_Github/{_push_all → modifies_the_repo/_push_all}/pushes_the_file_to_the_right_place.yml +60 -60
  39. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_push_blob/pushes_the_blob_even_when_it_is_larger_than_block_size.yml +181 -0
  40. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_push_item/pushes_a_single_item_and_makes_a_commit.yml +687 -0
  41. data/spec/cassettes/Worochi_Agent_Github/modifies_the_repo/_stream_blob/streams_the_file_as_an_Base64_JSON_field.yml +181 -0
  42. data/spec/cassettes/Worochi_OAuth/_flow_end/rejects_bad_code.yml +56 -0
  43. data/spec/{helper.rb → spec_helper.rb} +14 -1
  44. data/spec/support/aws_uri_matcher.rb +1 -1
  45. data/spec/support/shared_exampes_for_agents.rb +13 -2
  46. data/spec/support/test_files.rb +4 -4
  47. data/spec/worochi/agent/dropbox_spec.rb +29 -3
  48. data/spec/worochi/agent/github_spec.rb +54 -26
  49. data/spec/worochi/agent_spec.rb +34 -1
  50. data/spec/worochi/config_spec.rb +46 -30
  51. data/spec/worochi/helper/github_helper_spec.rb +94 -0
  52. data/spec/worochi/helper_spec.rb +15 -3
  53. data/spec/worochi/item_spec.rb +9 -6
  54. data/spec/worochi/log_spec.rb +30 -0
  55. data/spec/worochi/oauth_spec.rb +33 -0
  56. data/spec/worochi_spec.rb +25 -1
  57. data/worochi.gemspec +5 -1
  58. metadata +104 -11
  59. data/lib/worochi/helper/github.rb +0 -100
  60. data/spec/worochi/helper/github_spec.rb +0 -57
@@ -1,18 +1,34 @@
1
- require 'aws-sdk' unless Worochi::Config.s3_bucket.nil?
2
-
3
1
  class Worochi
4
2
  # Contains any global helper methods not specific to any individual service.
5
3
  module Helper
6
4
  class << self
7
5
  # Given an S3 path, return the full URL for the corresponding object
8
- # determined using the AWS SDK.
6
+ # determined using the AWS SDK. AWS_SECRET_ACCESS_KEY and
7
+ # AWS_ACCESS_KEY_ID should be present in ENV. The string should be
8
+ # formatted as: `s3:(bucket_name:)path/to/file`.
9
9
  #
10
- # @param path [String]
11
- # @return [URI::HTTP]
10
+ # @param path [String] S3 path
11
+ # @return [URI::HTTPS] URI of the file on S3
12
+ # @example Pre-configured bucket name
13
+ # Worochi::Config.s3_bucket = 'worochi'
14
+ # Worochi::Helper.s3_url('s3:test/path')
15
+ # # => #<URI::HTTPS URL:https://worochi.s3.amazonaws.com/test/path?AWSAccessKeyId=...>
16
+ # @example Custom bucket name
17
+ # Worochi::Helper.s3_url('s3:bucket-name:a/b')
18
+ # # => #<URI::HTTPS URL:https://bucket-name.s3.amazonaws.com/a/b?AWSAccessKeyId=...>
19
+ # @example Invalid syntax
20
+ # Worochi::Helper.s3_url('www.a.com/b.txt')
21
+ # # => Worochi::Error
12
22
  def s3_url(path)
13
- raise Error, 'S3 bucket name is not defined' if Config.s3_bucket.nil?
23
+ raise Error, 'Invalid S3 path' unless is_s3_path?(path)
14
24
  path = path.sub(s3_prefix_re, '')
15
- AWS::S3.new.buckets[Config.s3_bucket].objects[path].url_for(:read)
25
+ if match = /^(.*)\:/.match(path)
26
+ bucket = match[1]
27
+ path = path.sub(/^(.*)\:/, '')
28
+ end
29
+ bucket ||= Config.s3_bucket
30
+ raise Error, 'S3 bucket name is not defined' if bucket.nil?
31
+ AWS::S3.new.buckets[bucket].objects[path].url_for(:read)
16
32
  end
17
33
 
18
34
  # Check if a given path is an S3 path.
@@ -33,4 +49,9 @@ class Worochi
33
49
  end
34
50
  end
35
51
  end
52
+ end
53
+
54
+ # Load all helpers
55
+ Dir[File.join(File.dirname(__FILE__), 'helper/[^#]*.rb')].each do |file|
56
+ require 'worochi/helper/' + File.basename(file, '.rb')
36
57
  end
data/lib/worochi/item.rb CHANGED
@@ -102,8 +102,10 @@ class Worochi
102
102
  if File.file?(source)
103
103
  retrieve_local(source)
104
104
  else
105
- url = Helper.is_s3_path?(source) ? Helper.s3_url(source) : source
106
- retrieve_remote(url)
105
+ if Config.s3_enabled? && Helper.is_s3_path?(source)
106
+ source = Helper.s3_url(source)
107
+ end
108
+ retrieve_remote(source)
107
109
  end
108
110
  end
109
111
 
@@ -118,7 +120,7 @@ class Worochi
118
120
  file
119
121
  end
120
122
 
121
- # Downloads a remote file using {HTTP::Get}.
123
+ # Downloads a remote file using `HTTP::Get`.
122
124
  #
123
125
  # @param file_url [String, URI] the URL of the file
124
126
  # @return [Tempfile] the downloaded file
data/lib/worochi/log.rb CHANGED
@@ -13,8 +13,10 @@ class Worochi
13
13
  }
14
14
  class << self
15
15
  # Initializes the logging system.
16
- def init_log
17
- @logger = Logger.new(STDOUT)
16
+ #
17
+ # @param logdev [IO] target device to log to
18
+ def init(logdev=nil)
19
+ @logger = Logger.new(logdev || Config.logdev)
18
20
  @logger.formatter = proc do |severity, datetime, progname, msg|
19
21
  "[\033[#{SEVERITY_COLOR[severity]}m#{severity}\033[0m]: #{msg}\n"
20
22
  end
@@ -22,30 +24,22 @@ class Worochi
22
24
 
23
25
  # Prints DEBUG messages
24
26
  def debug(message)
25
- return if Worochi::Config.silent?
26
- init_log if @logger.nil?
27
- @logger.debug message
27
+ @logger.debug message unless Worochi::Config.silent?
28
28
  end
29
29
 
30
30
  # Prints WARN messages
31
31
  def warn(message)
32
- return if Worochi::Config.silent?
33
- init_log if @logger.nil?
34
- @logger.warn message
32
+ @logger.warn message unless Worochi::Config.silent?
35
33
  end
36
34
 
37
35
  # Prints INFO messages
38
36
  def info(message)
39
- return if Worochi::Config.silent?
40
- init_log if @logger.nil?
41
- @logger.info message
37
+ @logger.info message unless Worochi::Config.silent?
42
38
  end
43
39
 
44
40
  # Prints ERROR messages
45
41
  def error(message)
46
- return if Worochi::Config.silent?
47
- init_log if @logger.nil?
48
- @logger.error message
42
+ @logger.error message unless Worochi::Config.silent?
49
43
  end
50
44
  end
51
45
  end
@@ -0,0 +1,69 @@
1
+ require 'oauth2'
2
+
3
+ class Worochi
4
+ # Implements OAuth2 authorization code flow for obtaining user tokens.
5
+ class OAuth
6
+ # OAuth2 options.
7
+ # @return [Hashie::Mash]
8
+ attr_accessor :options
9
+
10
+ # The OAuth2 client
11
+ # @return [OAuth2::Client]
12
+ attr_reader :client
13
+
14
+ # @param service [Symbol] service name
15
+ # @param redirect_url [String] callback URL if required
16
+ def initialize(service, redirect_uri=nil)
17
+ @options = Worochi::Config.service_opts(service).oauth
18
+ options.service = service
19
+ options.redirect_uri = redirect_uri
20
+ opts = { site: options.site }
21
+ opts[:authorize_url] = options.authorize_url if options.authorize_url
22
+ opts[:token_url] = options.token_url if options.token_url
23
+ @client = OAuth2::Client.new(id, secret, opts)
24
+ end
25
+
26
+ # Returns the URL to start the authorization flow.
27
+ #
28
+ # @param state [String] optional security verification state
29
+ # @return [String] URL to begin flow
30
+ def flow_start(state=nil)
31
+ client.site = options.site
32
+ opts = { scope: scope }
33
+ opts[:state] = state if state
34
+ opts[:redirect_uri] = options.redirect_uri if options.redirect_uri
35
+ client.auth_code.authorize_url(opts)
36
+ end
37
+
38
+ # Retrieves the token using the temporary authorization code.
39
+ #
40
+ # @param code [String] authorization code from the first part
41
+ # @return [OAuth2::AccessToken] OAuth2 token
42
+ def flow_end(code)
43
+ client.site = options.token_site || options.site
44
+ opts = {}
45
+ opts[:redirect_uri] = options.redirect_uri if options.redirect_uri
46
+ client.auth_code.get_token(code, opts)
47
+ end
48
+
49
+ alias_method :get_token, :flow_end
50
+
51
+ private
52
+ # @return [String] scope
53
+ def scope
54
+ options.scope || ''
55
+ end
56
+
57
+ # @return [String] environmental variable for client ID
58
+ def id
59
+ var = options.id_env || options.service.to_s.upcase + '_ID'
60
+ ENV[var]
61
+ end
62
+
63
+ # @return [String] environmental variable for client secret
64
+ def secret
65
+ var = options.secret_env || options.service.to_s.upcase + '_SECRET'
66
+ ENV[var]
67
+ end
68
+ end
69
+ end
@@ -1,4 +1,4 @@
1
1
  class Worochi
2
2
  # Current version of the gem
3
- VERSION = '0.0.7'
3
+ VERSION = '0.0.10'
4
4
  end
data/lib/worochi.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require 'hashie'
2
+ require 'aws-sdk'
1
3
  require 'worochi/config'
2
4
  require 'worochi/error'
3
5
  require 'worochi/log'
4
- require 'worochi/helper'
5
6
  require 'worochi/item'
6
7
  require 'worochi/agent'
8
+ require 'worochi/oauth'
9
+ require 'worochi/helper'
7
10
 
8
11
  # The main class for the gem. This and the {Agent} class are the main
9
12
  # endpoints for interacting with the remote services.
@@ -16,6 +19,15 @@ class Worochi
16
19
  # @return [Array]
17
20
  attr_reader :agents
18
21
 
22
+ # Initialize configurations and logging.
23
+ #
24
+ # @return [nil]
25
+ def init
26
+ Config.load_yaml
27
+ Log.init
28
+ reset
29
+ end
30
+
19
31
  # Creates a new {Worochi::Agent} and adds it to the list of agents
20
32
  # listening to {Worochi.push} requests.
21
33
  #
@@ -113,9 +125,14 @@ class Worochi
113
125
  # @see Item.open
114
126
  # @see Agent#push
115
127
  def push(origin, opts={})
116
- Log.warn 'No push targets specified' and return false if @agents.empty?
128
+ if @agents.empty?
129
+ Log.warn 'No push targets specified'
130
+ return false
131
+ end
117
132
  @agents.each { |agent| agent.push(origin, opts) }
118
133
  true
119
134
  end
120
135
  end
121
- end
136
+ end
137
+
138
+ Worochi.init