hubic 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 sdalu
3
+ Copyright (c) 2014 Stephane D'Alu
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -4,11 +4,25 @@ Hubic
4
4
  Requirement
5
5
  -----------
6
6
  You need to retrieve the client id, secret key, and redirection url.
7
- For that if not alredy done you need to register an application into your account.
8
- To start the registration process you will need to go to ``My Account``, select ``Your application``, and click on ``Add an application``.
7
+ For that if not already done you need to register an application into
8
+ your account.
9
+ To start the registration process you will need to go to ``My Account``,
10
+ select ``Your application``, and click on ``Add an application``.
9
11
 
10
12
  Quick example
11
13
  -------------
14
+ From the commande line:
15
+
16
+ ```sh
17
+ HUBIC_USER=foo@bar.com # Set the user on which we will act
18
+ hubic client config # Configure the client API key
19
+ hubic auth # Authenticate the user
20
+ hubic upload file.txt cloud/file.txt # Upload file
21
+ hubic download cloud/file.txt # Download file
22
+ hubic delete cloud/file.txt # Remove file
23
+ ```
24
+
25
+ From a ruby script:
12
26
  ```ruby
13
27
  require 'hubic'
14
28
 
data/Rakefile CHANGED
@@ -3,9 +3,14 @@
3
3
  require "rbconfig"
4
4
  require "rubygems"
5
5
  require "bundler/setup"
6
+ require "yard"
6
7
 
7
8
  include Rake::DSL
8
9
 
9
10
 
10
11
  Bundler::GemHelper.install_tasks
11
12
 
13
+ YARD::Rake::YardocTask.new do |t|
14
+ t.files = ['lib/**/*.rb'] # optional
15
+ # t.options = ['--any', '--extra', '--opts'] # optional
16
+ end
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'hubic'
6
+ require 'highline'
7
+
8
+
9
+ HUBIC_CLIENT_CFG = "#{ENV['HOME']}/.hubic-client"
10
+
11
+ exclusive_options = []
12
+ container = nil
13
+ user = ENV['HUBIC_USER']
14
+
15
+ error_proc = lambda do |msg|
16
+ $stderr.puts(msg)
17
+ exit 1
18
+ end
19
+
20
+
21
+ options = OptionParser.new do |opts|
22
+ opts.banner = "Hubic: access your data"
23
+ opts.define_head "Usage: hubic [options] <uri|path> [file]"
24
+ opts.separator ""
25
+ opts.separator "Examples:"
26
+ opts.separator " HUBIC_USER=foo@bar.com"
27
+ opts.separator " hubic client config"
28
+ opts.separator " hubic auth"
29
+ opts.separator " hubic upload local-file.txt documents/cloud-file.txt"
30
+ opts.separator " hubic download documents/cloud-file.txt"
31
+ opts.separator " hubic delete documents/cloud-file.txt"
32
+ opts.separator ""
33
+ opts.separator "Options:"
34
+
35
+ opts.on_tail("-h", "--help", "Show this message") do
36
+ puts opts
37
+ exit
38
+ end
39
+
40
+ opts.on("-c", "--container STRING", "Use the give container as default") do |v|
41
+ container = v
42
+ exclusive_options << :container
43
+ end
44
+
45
+
46
+ opts.on("-u", "--user STRING", "User account to use") do |v|
47
+ user = v
48
+ end
49
+
50
+ opts.on("-V", "--verbose", "Be verbose about action performed") do
51
+ require 'logger'
52
+ loggers << Logger.new($stdout)
53
+ end
54
+
55
+ opts.on_tail("-v", "--version", "Show version") do
56
+ puts "Hubic #{Hubic::VERSION}"
57
+ exit
58
+ end
59
+ end
60
+ opts = options
61
+ opts.parse!
62
+
63
+ $term = HighLine.new
64
+
65
+ action = ARGV.shift
66
+
67
+ # Manage client configuration
68
+ if action == 'client'
69
+ case ARGV[0]
70
+ when 'config'
71
+ ARGV.shift
72
+ cfg = case ARGV.length
73
+ when 0
74
+ [ $term.ask("Client ID : ").to_s,
75
+ $term.ask("Client Secret: ").to_s,
76
+ $term.ask("Redirect URI : ").to_s ]
77
+ when 3
78
+ ARGV
79
+ else
80
+ error_proc["hubic client config [client_id client_secret_ redirect_uri"]
81
+ end
82
+ File.open(HUBIC_CLIENT_CFG, 'w', 0600) {|io|
83
+ io.write({ 'client_id' => cfg[0],
84
+ 'client_secret' => cfg[1],
85
+ 'redirect_uri' => cfg[2], }.to_yaml)
86
+ }
87
+ exit
88
+ when 'reset'
89
+ File.unlink(HUBIC_CLIENT_CFG)
90
+ exit
91
+ end
92
+ end
93
+
94
+
95
+ # Configure Hubic client
96
+ if ENV.include?('HUBIC_REDIRECT_URI' ) &&
97
+ ENV.include?('HUBIC_CLIENT_ID' ) &&
98
+ ENV.include?('HUBIC_CLIENT_SECRET')
99
+ Hubic.default_redirect_uri = ENV['HUBIC_REDIRECT_URI' ]
100
+ Hubic.default_client_id = ENV['HUBIC_CLIENT_ID' ]
101
+ Hubic.default_client_secret = ENV['HUBIC_CLIENT_SECRET']
102
+ else
103
+ begin
104
+ cfg = YAML.load_file(HUBIC_CLIENT_CFG)
105
+ Hubic.default_redirect_uri = cfg['redirect_uri' ]
106
+ Hubic.default_client_id = cfg['client_id' ]
107
+ Hubic.default_client_secret = cfg['client_secret']
108
+ rescue Errno::ENOENT
109
+ error_proc["Plase run: hubic client config"]
110
+ end
111
+ end
112
+
113
+ if user.nil?
114
+
115
+ end
116
+
117
+
118
+ case action
119
+ when 'auth'
120
+ Hubic.for_user(user, ARGV[0], force: true) {|user|
121
+ ($term.ask("Password for #{user}: ", String) {|q| q.echo = 'x' }).to_s
122
+ }
123
+ when 'download' # hubic / local
124
+ obj = ARGV[0]
125
+ dst = ARGV[1] || File.basename(obj)
126
+ Hubic.for_user(user).download(obj, dst)
127
+ when 'upload' # local / hubic
128
+ src = ARGV[0]
129
+ obj = ARGV[1]
130
+ Hubic.for_user(user).upload(src, obj)
131
+ end
@@ -13,8 +13,11 @@ Gem::Specification.new do |s|
13
13
  s.description = "Manage your Hubic account from Ruby"
14
14
 
15
15
  s.add_dependency "faraday", "~>0.9"
16
+ s.add_dependency "mime-types"
17
+ s.add_dependency "highline"
16
18
  s.add_dependency "nokogiri"
17
19
  s.add_development_dependency "rake"
20
+ s.add_development_dependency "yard"
18
21
 
19
22
  s.files = `git ls-files`.split("\n")
20
23
  s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
@@ -32,32 +32,46 @@ class Hubic
32
32
  end
33
33
  end
34
34
 
35
-
35
+ # Set the default client Id to use
36
36
  def self.default_client_id=(client_id)
37
37
  @@client_id = client_id
38
38
  end
39
39
 
40
+ # Set the default client Secret to use
40
41
  def self.default_client_secret=(client_secret)
41
42
  @@client_secret = client_secret
42
43
  end
43
44
 
45
+ # Set the default redirect URI to use
44
46
  def self.default_redirect_uri=(redirect_uri)
45
47
  @@redirect_uri = redirect_uri
46
48
  end
47
49
 
48
-
49
- def self.for_user(user, password=nil, store: Store[user],
50
- &password_requester)
50
+ # Create a Hubic handler
51
+ # @param user [String]
52
+ # @param password [String]
53
+ # @param store
54
+ # @param force [true, false]
55
+ # @param password_requester
56
+ # @return [Hubic] an Hubic handler
57
+ def self.for_user(user, password=nil,
58
+ store: Store[user], force: false, &password_requester)
51
59
  h = Hubic.new(@@client_id, @@client_secret, @@redirect_uri)
52
- h.for_user(user, password, store: store, &password_requester)
60
+ h.for_user(user, password,
61
+ store: store, force: force, &password_requester)
53
62
  h
54
63
  end
55
64
 
56
65
 
66
+ # Create a Hubic handler
67
+ # @param client_id
68
+ # @param client_secret
69
+ # @param redirect_uri
57
70
  def initialize(client_id = @@client_id,
58
71
  client_secret = @@client_secret,
59
72
  redirect_uri = @@redirect_uri)
60
73
  @store = nil
74
+ @refresh_token = nil
61
75
  @client_id = client_id
62
76
  @client_secret = client_secret
63
77
  @redirect_uri = redirect_uri
@@ -69,9 +83,16 @@ class Hubic
69
83
  @default_container = "default"
70
84
  end
71
85
 
72
- def for_user(user, password=nil, store: Store[user], &password_requester)
86
+ # Initialize the Hubic handler to perform operations on behalf of the user
87
+ # @param user [String]
88
+ # @param password [String]
89
+ # @param store
90
+ # @param force [true, false]
91
+ # @param password_requester
92
+ def for_user(user, password=nil,
93
+ store: Store[user], force: false, &password_requester)
73
94
  @store = store
74
- @refresh_token = @store['refresh_token'] if @store
95
+ @refresh_token = @store['refresh_token'] if @store && !force
75
96
 
76
97
  if @refresh_token
77
98
  data = refresh_access_token
@@ -95,6 +116,10 @@ class Hubic
95
116
  end
96
117
 
97
118
 
119
+
120
+
121
+
122
+
98
123
  def account
99
124
  api_hubic(:get, '/1.0/account')
100
125
  end
@@ -103,14 +128,17 @@ class Hubic
103
128
  api_hubic(:get, '/1.0/account/credentials')
104
129
  end
105
130
 
106
-
107
-
108
- def [](path=nil, container=@default_container)
109
- # objects(path, container: container)
131
+ def usage
132
+ api_hubic(:get, '/1.0/account/usage')
110
133
  end
111
134
 
112
-
113
135
 
136
+
137
+ # Make a call to the Hubic API
138
+ # @param method [:get, :post, :delete]
139
+ # @param path
140
+ # @param params [Hash]
141
+ # @return [Hash]
114
142
  def api_hubic(method, path, params=nil)
115
143
  r = @conn.method(method).call(path) do |req|
116
144
  req.headers['Authorization'] = "Bearer #{@access_token}"
@@ -121,7 +149,12 @@ class Hubic
121
149
 
122
150
  private
123
151
 
124
-
152
+ # Obtain a request code from the Hubic server.
153
+ # We will ask for the code, and validate the form on the user behalf.
154
+ #
155
+ # @param user [String]
156
+ # @param password [String]
157
+ # @return [String] the request code
125
158
  def get_request_code(user, password)
126
159
  # Request code (retrieve user confirmation form)
127
160
  r = @conn.get '/oauth/auth', {
@@ -168,6 +201,9 @@ class Hubic
168
201
  end
169
202
  end
170
203
 
204
+ # Request an access token, this will also acquiere a refresh token.
205
+ # @param code [String] the request code
206
+ # @return Hash
171
207
  def get_access_token(code)
172
208
  r = @conn.post '/oauth/token', {
173
209
  :code => code,
@@ -190,6 +226,8 @@ class Hubic
190
226
  end
191
227
  end
192
228
 
229
+ # Refresh the access token
230
+ # @return Hash
193
231
  def refresh_access_token
194
232
  if @refresh_token.nil?
195
233
  raise Error, "refresh_token was not previously acquiered"
@@ -1,9 +1,9 @@
1
- class Hubic
1
+ require 'mime/types'
2
2
 
3
- # File operations
4
- #######################################################################
3
+ class Hubic
5
4
 
6
5
  def download(obj, dst=nil, size: nil, offset: 0, &block)
6
+ # Handle file name or nil as a posible destination
7
7
  io = nil
8
8
  dst = Pathname(dst) if String === dst
9
9
  _dst = case dst
@@ -12,12 +12,16 @@ class Hubic
12
12
  else dst
13
13
  end
14
14
 
15
+ # Get object
15
16
  meta = get_object(obj, _dst, size: size, offset: offset, &block)
16
17
 
18
+ # If file name update the timestamp
17
19
  if (Pathname === dst) && meta[:lastmod]
18
20
  dst.utime(meta[:lastmod], meta[:lastmod])
19
21
  end
20
-
22
+
23
+ # If destination is nil, returns the downloaded file
24
+ # insteaded of the meta data
21
25
  if dst.nil?
22
26
  then io.flush.string
23
27
  else meta
@@ -26,8 +30,13 @@ class Hubic
26
30
  io.close unless io.nil?
27
31
  end
28
32
 
29
- def upload(src, obj, &block)
30
- put_object(src, obj, &block)
33
+ def upload(src, obj, type='application/octet-stream', &block)
34
+ case src
35
+ when String, Pathname
36
+ type = (MIME::Types.of(src).first ||
37
+ MIME::Types['application/octet-stream'].first).content_type
38
+ end
39
+ put_object(obj, src, type, &block)
31
40
  end
32
41
 
33
42
  def copy(src, dst)
@@ -118,16 +118,49 @@ class Hubic
118
118
  http.finish unless http.nil?
119
119
  end
120
120
 
121
- def put_object(src, obj, &block)
121
+ def put_object(obj, src, type='application/octet-stream', &block)
122
122
  container, path, uri = normalize_object(obj)
123
+ io = File.open(src)
123
124
 
124
- r = @conn.put(uri) do |req|
125
- req.headers['X-Auth-Token'] = @os[:token]
126
- req.params[:file] = Faraday::UploadIO.new(src, 'text/plain')
125
+ hdrs = {}
126
+ hdrs['X-Auth-Token' ] = @os[:token]
127
+ hdrs['Transfer-Encoding'] = 'chunked'
128
+ hdrs['Content-Type' ] = type
129
+
130
+ http = Net::HTTP.new(uri.host, uri.port)
131
+ if uri.scheme == 'https'
132
+ http.use_ssl = true
133
+ # http.verify_mode = OpenSSL::SSL::VERIFY_NONE
127
134
  end
128
- puts r.inspect
135
+ http.start
136
+
137
+ request = Net::HTTP::Put.new(uri.request_uri, hdrs)
138
+ request.body_stream = io
139
+ http.request(request) {|response|
140
+ case response
141
+ when Net::HTTPSuccess
142
+ when Net::HTTPRedirection
143
+ fail "http redirect is not currently handled"
144
+ when Net::HTTPUnauthorized
145
+ # TODO: Need to refresh token
146
+ else
147
+ fail "resource unavailable: #{uri} (#{response.class})"
148
+ end
149
+
150
+ puts response.inspect
151
+ }
152
+ if block
153
+ block.call(:done)
154
+ end
155
+ ensure
156
+ io.close unless io.nil?
157
+ http.finish unless http.nil?
129
158
  end
130
159
 
160
+ # List objects store in a container.
161
+ #
162
+ # @param container [String] the name of the container.
163
+ # @return [Array] the list of objects (as a Hash)
131
164
  def objects(container = @default_container,
132
165
  path: nil, limit: nil, gt: nil, lt: nil)
133
166
  path = path[1..-1] if path && path[0] == ?/
@@ -163,7 +196,7 @@ class Hubic
163
196
  params[:format] ||= :json
164
197
 
165
198
  p = "#{@os[:endpoint]}#{'/' if path[0] != ?/}#{path}"
166
- r = @conn.method(method).call(p) do |req|
199
+ r = @os[:conn].method(method).call(p) do |req|
167
200
  req.headers['X-Auth-Token'] = @os[:token]
168
201
  req.params = params
169
202
  end
@@ -188,6 +221,7 @@ class Hubic
188
221
 
189
222
  def openstack_setup(endpoint, token, expires)
190
223
  conn = Faraday.new do |faraday|
224
+ faraday.request :multipart
191
225
  faraday.request :url_encoded
192
226
  faraday.adapter :net_http
193
227
  faraday.options.params_encoder = Faraday::FlatParamsEncoder
@@ -201,6 +235,8 @@ class Hubic
201
235
  end
202
236
 
203
237
  def normalize_object(obj)
238
+ openstack_setup_refresh
239
+
204
240
  c, p = case obj
205
241
  when String
206
242
  [ @default_container, obj ]
@@ -213,6 +249,8 @@ class Hubic
213
249
  when 2 then Symbol === obj[1] ? [ obj[1], obj[0] ] : obj
214
250
  else raise ArguementError
215
251
  end
252
+ else
253
+ raise ArgumentError
216
254
  end
217
255
  c = c.to_s
218
256
  p = p[1..-1] if p[0] == ?/
@@ -1,3 +1,3 @@
1
1
  class Hubic
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-20 00:00:00.000000000 Z
12
+ date: 2014-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -27,6 +27,38 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.9'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mime-types
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: highline
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
30
62
  - !ruby/object:Gem::Dependency
31
63
  name: nokogiri
32
64
  requirement: !ruby/object:Gem::Requirement
@@ -59,10 +91,27 @@ dependencies:
59
91
  - - '>='
60
92
  - !ruby/object:Gem::Version
61
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: yard
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
62
110
  description: Manage your Hubic account from Ruby
63
111
  email:
64
112
  - sdalu@sdalu.com
65
- executables: []
113
+ executables:
114
+ - hubic
66
115
  extensions: []
67
116
  extra_rdoc_files: []
68
117
  files:
@@ -71,6 +120,7 @@ files:
71
120
  - LICENSE
72
121
  - README.md
73
122
  - Rakefile
123
+ - bin/hubic
74
124
  - hubic.gemspec
75
125
  - lib/hubic.rb
76
126
  - lib/hubic/file_ops.rb
@@ -91,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
141
  version: '0'
92
142
  segments:
93
143
  - 0
94
- hash: 4363560357882864147
144
+ hash: 254901150746708933
95
145
  required_rubygems_version: !ruby/object:Gem::Requirement
96
146
  none: false
97
147
  requirements:
@@ -100,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
150
  version: '0'
101
151
  segments:
102
152
  - 0
103
- hash: 4363560357882864147
153
+ hash: 254901150746708933
104
154
  requirements: []
105
155
  rubyforge_project:
106
156
  rubygems_version: 1.8.29
@@ -108,3 +158,4 @@ signing_key:
108
158
  specification_version: 3
109
159
  summary: Manage your Hubic account from Ruby
110
160
  test_files: []
161
+ has_rdoc: