google_storage 0.0.3

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.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea
6
+
7
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in google_storage.gemspec
4
+ gemspec
data/README.textile ADDED
@@ -0,0 +1,110 @@
1
+ h1. Google Storage using API v2
2
+
3
+ I wrote this gem because the only google storage gems I could find already written were either written a while ago and only set up to use the old
4
+ version of Google's API or they were dependent on Gems that don't run properly on... dare I say it... windows.. :) Apologies, I'm without choice
5
+ at the moment, but anyways, this gem should run fine on all platforms and I've tried to keep dependencies to a minimum. Let me know if you find
6
+ any bugs though ok and feel free to contribute.
7
+
8
+ Google Storage is still a little experimental at the moment and the responses back from google differ quite a bit from each other.
9
+ I've tried to parse all of these different responses and turn them into a fairly common type of response object though.
10
+
11
+ h2. Setup Guide
12
+
13
+ There's a couple of steps to follow in order to setup this gem. The new Google Storage APIv2 uses OAuth 2.0 to authenticate requests, you can read up
14
+ more on the nitty gritty if you like here: "Google's OAuth2 Guide":http://code.google.com/apis/accounts/docs/OAuth2.html
15
+
16
+ I'll try and add client side support also once this gem is up and running properly, but for the moment it's only setup to support server side web
17
+ applications.
18
+
19
+ But it's also possible to run this gem from the command line if you want.
20
+
21
+
22
+ h2. Install the google_storage Gem
23
+
24
+ Include the google_storage gem in your Gemfile and install config files
25
+ <pre>gem "google_storage"
26
+ bundle install
27
+ </pre>
28
+ Then in your Rails application directory run:
29
+ <pre>rails generate google_storage:install
30
+ </pre>
31
+ This will generate some rake tasks a google_storage.yml file in your config directory.
32
+ <pre>/Application/config/google_storage.yml
33
+ /Application/lib/tasks/google_storage.task
34
+ </pre>
35
+
36
+
37
+
38
+ h2. Setup your Google Project Client ID's
39
+
40
+ Visit "Google Storage":http://code.google.com/apis/storage/ and select activate Google Storage.
41
+ If you haven't already got a project set up, it'll prompt you to create one.
42
+
43
+ When you have access to your Google APIs Console, you need to enable Google Storage. When you select enable, you'll be shown terms and conditions
44
+ and you'll then need to setup billing. They have full pricing details there for you to check out as well but I think it's pretty reasonable..
45
+
46
+ Create a client ID for your project
47
+ On the left menu select "API Access" and then "Create an OAuth 2.0 client ID"
48
+ Enter your project's name and brand information.
49
+
50
+ Select Application type = Web Application and enter your site's information. If you're using localhost and running
51
+ locally make sure you include the port number you're using as well.
52
+
53
+
54
+ h2. Enter your Client ID details into your google_storage.yml
55
+
56
+ This is the example google_storage.yml file that is copied into your config directory of your rails application.
57
+
58
+ Follow the steps to obtain a refresh token from google.
59
+
60
+ <pre>
61
+ #Replace the following example ids with your own
62
+
63
+ google_config:
64
+ x-goog-project-id: 825628431245
65
+
66
+ #Client ID for web applications
67
+ web_applications:
68
+ client_id: 825628431245.apps.googleusercontent.com
69
+ client_secret: lpNYX5SPFDB6N-40lyMIPlQn
70
+ redirect_uris: 'http://localhost:3000/example'
71
+ js_origins: 'http://localhost:3000'
72
+
73
+ #refresh_token: replace this line with a refresh token from google, read below on how to get one
74
+
75
+ #You need to acquire a refresh token from google so that the google_storage gem
76
+ #can acquire access tokens whenever it needs to make new requests
77
+
78
+ # 1. Make sure you've signed up for Google Storage and filled in the above client ID details
79
+ # for your web application first
80
+ #
81
+ # 2. Depending on how much access you want to grant to your application run
82
+ # ONE of the following from your applications root directory. If you intend to be able to create and
83
+ # destroy objects and buckets and also be able to set permissions then use full_control
84
+ #
85
+ # rake gs:grant:read_only
86
+ # rake gs:grant:read_write
87
+ # rake gs:grant:full_control
88
+ #
89
+ # 3. Step 2 will generate a URL for you. Copy and paste the URL into a browser and you should be prompted
90
+ # by google to authorize the request by logging into your browser using the google email account you setup
91
+ # your google storage account with
92
+ #
93
+ # 4. When you 'allow access' you'll be redirected back to the redirect URL you setup in your client ID
94
+ # Your redirect URL should now include an authorization code. It'll look something like this:
95
+ # http://localhost:3000/example?code=4/WvlklnjtybhRJpaKpmDYrzIhAzyx
96
+ #
97
+ # 5. Copy that code from your URL and run the following rake task from your application directory
98
+ #
99
+ # rake gs:refresh_token['paste_your_auth_code_here']
100
+ # Example: rake gs:refresh_token['4/WvlklnjtybhRJpaKpmDYrzIhAzyx']
101
+ #
102
+ # 6. If everything worked you should see something that looks like the following:
103
+ #
104
+ # refresh_token: 1/x4X-U57snRMkLIWWYHWLCXPbfcnyGsdfx04sWAiG_1k
105
+ #
106
+ # 7. Copy and paste the refresh_token into this file. Your application should now be able to make calls to your
107
+ # Google Storage API
108
+ </pre>
109
+
110
+ Once you've acquired your refresh_token you can now make calls to the API. Refer to the examples dir on how to use.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
@@ -0,0 +1,60 @@
1
+ ### Configuration ###
2
+ #
3
+ # require "google_storage"
4
+ #
5
+ # The following will look for google_storage.yml in your rails config directory
6
+ # gs_client = GoogleStorage::Client.new
7
+ #
8
+ # Otherwise you can pass in the path to the google_storage.yml
9
+ # gs_client = GoogleStorage::Client.new(:config_yml => 'C:/example_path/google_storage.yml')
10
+ #
11
+ ### Service Requests ###
12
+ #
13
+ # GET Service
14
+ # gs_client.list_buckets
15
+ #
16
+ ### Bucket Requests ###
17
+ #
18
+ # GET Access Control List for Bucket
19
+ # gs_client.list_acls_for_bucket('bucket_name')
20
+ # gs_client.bucket_acls('bucket_name')
21
+ #
22
+ # PUT Bucket
23
+ # gs_client.create_bucket('bucket_name') <-- private bucket
24
+ # gs_client.create_bucket('bucket_name', :x_goog_acl => 'public-read') <-- public bucket
25
+ #
26
+ # GET Bucket
27
+ # gs_client.get_bucket('bucket_name')
28
+ # gs_client.bucket_contents('bucket_name')
29
+ #
30
+ # DELETE Bucket
31
+ # gs_client.delete_bucket('bucket_name')
32
+ #
33
+ ### Object Requests ###
34
+ #
35
+ # GET Access Control List for Object
36
+ # gs_client.list_acls_for_object('bucket_name', 'object_name')
37
+ # gs_client.object_acls('bucket_name', 'object_name')
38
+ #
39
+ # GET Object
40
+ # gs_client.get_object('bucket_name', 'object_name')
41
+ # gs_client.get_object('bucket_name', 'object_name', :write_to_file => '/tmp/example/file.jpg')
42
+ #
43
+ # POST Object
44
+ # !!!! NOT ADDING POST METHOD AT THIS STAGE AS REQUIRES USE OF API V1 USING LEGACY ACCESS KEY
45
+ # !!!! USE PUT METHOD INSTEAD TO UPLOAD FILES
46
+ #
47
+ # PUT Object
48
+ # gs_client.put_object('bucket_name', 'object_name', :data => File.read('/tmp/example/file.jpg'), :x_goog_acl => 'public-read')
49
+ # gs_client.put_object('bucket_name', 'object_name', :path_to_file => '/tmp/example/file.jpg')
50
+ #
51
+ # HEAD Object
52
+ # gs_client.head_object('bucket_name', 'object_name')
53
+ #
54
+ # DELETE Object
55
+ # gs_client.delete_object('bucket_name', 'object_name')
56
+
57
+
58
+
59
+
60
+
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "google_storage/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "google_storage"
6
+ s.version = GoogleStorage::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Lucas Hills"]
9
+ s.email = ["lucas@lucashills.com"]
10
+ s.homepage = "https://github.com/2potatocakes/google_storage"
11
+ s.summary = "Google Storage for Developers is a RESTful service for storing and accessing your data on Google's infrastructure"
12
+ s.description = "A Ruby client library for using the new Google Storage API v2 using OAuth2.0"
13
+ s.files = `git ls-files`.split("\n")
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_dependency("crack", "~> 0.1.1")
17
+ s.require_paths = ["lib"]
18
+ s.extra_rdoc_files = ["README.textile"]
19
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ module GoogleStorage
4
+ # Copies a google_storage.yml file into your applications config directory and a rake file
5
+ # into your lib/tasks directory
6
+
7
+ class InstallGenerator < Rails::Generators::Base
8
+ desc "Copies a google_storage.yml file into your application"
9
+ source_root File.expand_path('../../../templates', __FILE__)
10
+
11
+ "Copies a google_storage.yml file into your applications config directory and a rake file into lib/tasks"
12
+ def generate_layout
13
+ copy_file 'google_storage.yml', 'config/google_storage.yml'
14
+ copy_file 'google_storage.rake', 'lib/tasks/google_storage.rake'
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'google_storage'
2
+
3
+ namespace :gs do
4
+ client = GoogleStorage::Client.new
5
+
6
+ namespace :grant do
7
+ desc "Google Storage URL to grant 'read only' access to your storage account"
8
+ task :read_only do
9
+ puts client.authorization_url(:read_only)
10
+ end
11
+
12
+ desc "Google Storage URL to grant 'read/write' access to your storage account"
13
+ task :read_write do
14
+ puts client.authorization_url(:read_write)
15
+ end
16
+
17
+ desc "Google Storage URL to grant 'read only' access to your storage account"
18
+ task :full_control do
19
+ puts client.authorization_url(:full_control)
20
+ end
21
+ end
22
+
23
+ desc "Acquire Google Storage refresh token"
24
+ task :refresh_token, :auth_code do |t, args|
25
+ puts "refresh_token: #{client.acquire_refresh_token(args[:auth_code])}"
26
+ end
27
+ end
@@ -0,0 +1,48 @@
1
+ #Replace the following example ids with your own
2
+
3
+ google_config:
4
+ x-goog-project-id: 825628431245
5
+
6
+ #Client ID for web applications
7
+ web_applications:
8
+ client_id: 825628431245.apps.googleusercontent.com
9
+ client_secret: lpNYX5SPFDB6N-40lyMIPlQn
10
+ redirect_uris: 'http://localhost:3000/example'
11
+ js_origins: 'http://localhost:3000'
12
+
13
+ #refresh_token: replace this line with a refresh token from google, read below on how to get one
14
+
15
+ #You need to acquire a refresh token from google so that the google_storage gem
16
+ #can acquire access tokens whenever it needs to make new requests
17
+
18
+ # 1. Make sure you've signed up for Google Storage and filled in the above client ID details
19
+ # for your web application first
20
+ #
21
+ # 2. Depending on how much access you want to grant to your application run
22
+ # ONE of the following from your applications root directory. If you intend to be able to create and
23
+ # destroy objects and buckets and also be able to set permissions then use full_control
24
+ #
25
+ # rake gs:grant:read_only
26
+ # rake gs:grant:read_write
27
+ # rake gs:grant:full_control
28
+ #
29
+ # 3. Step 2 will generate a URL for you. Copy and paste the URL into a browser and you should be prompted
30
+ # by google to authorize the request by logging into your browser using the google email account you setup
31
+ # your google storage account with
32
+ #
33
+ # 4. When you 'allow access' you'll be redirected back to the redirect URL you setup in your client ID
34
+ # Your redirect URL should now include an authorization code. It'll look something like this:
35
+ # http://localhost:3000/example?code=4/WvlklnjtybhRJpaKpmDYrzIhAzyx
36
+ #
37
+ # 5. Copy that code from your URL and run the following rake task from your application directory
38
+ #
39
+ # rake gs:refresh_token['paste_your_auth_code_here']
40
+ # Example: rake gs:refresh_token['4/WvlklnjtybhRJpaKpmDYrzIhAzyx']
41
+ #
42
+ # 6. If everything worked you should see something that looks like the following:
43
+ #
44
+ # refresh_token: 1/x4X-U57snRMkLIWWYHWLCXPbfcnyGsdfx04sWAiG_1k
45
+ #
46
+ # 7. Copy and paste the refresh_token into this file. Your application should now be able to make calls to your
47
+ # Google Storage API
48
+
@@ -0,0 +1,76 @@
1
+
2
+ module GoogleStorage
3
+ class Client
4
+
5
+ def list_buckets(options={})
6
+ options[:send_goog_project_id] = true
7
+ resp = get(nil, '/', options)
8
+ resp_obj = Crack::XML.parse(resp.body)
9
+ if resp_obj["ListAllMyBucketsResult"]
10
+ resp_obj[:success] = true
11
+ resp_obj[:buckets] = resp_obj["ListAllMyBucketsResult"]["Buckets"]["Bucket"]
12
+ resp_obj[:raw] = Crack::XML.parse(resp.body)
13
+ resp_obj.each_key {|key| resp_obj.delete(key) unless key == :success || key == :buckets || key == :raw }
14
+ end
15
+ return resp_obj
16
+ end
17
+
18
+ def list_acls_for_bucket(bucket, options={})
19
+ resp = get(bucket, '/?acl', options)
20
+ resp_obj = Crack::XML.parse(resp.body)
21
+ if resp_obj["AccessControlList"]
22
+ resp_obj[:success] = true
23
+ resp_obj[:bucket_name] = bucket
24
+ resp_obj[:acl] = resp_obj["AccessControlList"]
25
+ resp_obj[:raw] = Crack::XML.parse(resp.body)
26
+ resp_obj.each_key {|key| resp_obj.delete(key) unless key == :success || key == :bucket_name || key == :acl || key == :raw }
27
+ end
28
+ return resp_obj
29
+ end
30
+
31
+ alias :bucket_acls :list_acls_for_bucket
32
+
33
+ def create_bucket(bucket, options={})
34
+ options[:send_goog_project_id] = true
35
+ resp = put(bucket, '/', options)
36
+ resp_obj = Crack::XML.parse(resp.body)
37
+ if resp.code == "200"
38
+ resp_obj.clear
39
+ resp_obj[:success] = true
40
+ resp_obj[:bucket_name] = bucket
41
+ resp_obj[:message] = "Bucket created"
42
+ end
43
+ return resp_obj
44
+ end
45
+
46
+ def get_bucket(bucket, options={})
47
+ resp = get(bucket, '/', options)
48
+ resp_obj = Crack::XML.parse(resp.body)
49
+ if resp.code == "200"
50
+ resp_obj[:success] = true
51
+ resp_obj[:bucket_name] = bucket
52
+ contents = resp_obj["ListBucketResult"]["Contents"] ? Array.new : nil
53
+ resp_obj["ListBucketResult"]["Contents"].is_a?(Array) ? \
54
+ (contents = resp_obj["ListBucketResult"]["Contents"]) : \
55
+ (contents[0] = resp_obj["ListBucketResult"]["Contents"]) unless contents.nil?
56
+ resp_obj[:contents] = contents
57
+ resp_obj[:raw] = Crack::XML.parse(resp.body)
58
+ resp_obj.each_key {|key| resp_obj.delete(key) unless key == :success || key == :bucket_name || key == :contents || key == :raw }
59
+ end
60
+ return resp_obj
61
+ end
62
+
63
+ alias :bucket_contents :get_bucket
64
+
65
+ def delete_bucket(bucket, options={})
66
+ resp = delete(bucket, '/', options)
67
+ return Crack::XML.parse(resp.body) unless resp.code == "204"
68
+ resp_obj = {}
69
+ resp_obj[:success] = true
70
+ resp_obj[:bucket_name] = bucket
71
+ resp_obj[:message] = "Bucket deleted"
72
+ return resp_obj
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,111 @@
1
+ require 'google_storage/request'
2
+ require 'google_storage/token'
3
+ require 'google_storage/bucket'
4
+ require 'google_storage/object'
5
+ require 'yaml'
6
+
7
+ module GoogleStorage
8
+
9
+ class Client
10
+
11
+ def initialize(options = {})
12
+
13
+ if (options[:config_yml] && !options[:config_yml].nil?) || (defined?(Rails.root) && File.exists?(File.join(Rails.root, 'config', 'google_storage.yml')))
14
+ config_path = options[:config_yml] ? File.expand_path(options[:config_yml]) : File.join(Rails.root, 'config', 'google_storage.yml')
15
+ end
16
+
17
+ raise " \nCan't find a google_storage.yml file to initialise with..
18
+ \nIf running inside a Rails Application
19
+ Please run: rails generate google_storage:install
20
+ To generate a google_storage.yml file in your config directory
21
+ \nIf running manually within a script or whatever
22
+ Initialise GoogleStorage with a path to your config yml file
23
+ Example: GoogleStorage::Client.new(:config_yml => 'path to your google storage yml')
24
+ \nIf running a rake task try passing: path='path to your google storage yml'
25
+ \n\n" unless config_path && File.exists?(config_path)
26
+
27
+ config_yml = YAML::load(File.open(config_path))
28
+
29
+ @project_id = config_yml['google_config']['x-goog-project-id']
30
+
31
+ @client_id = config_yml['web_applications']['client_id']
32
+ @client_secret = config_yml['web_applications']['client_secret']
33
+ @client_secret.force_encoding("UTF-8")
34
+ @refresh_token = config_yml['refresh_token'] if config_yml['refresh_token']
35
+
36
+ #TODO Add support for individual permission types
37
+ if config_yml['google_storage_ids']
38
+ @gsid_you = config_yml['google_storage_ids']['you'] if config_yml['google_storage_ids']['you']
39
+ @gsid_owners = config_yml['google_storage_ids']['owners'] if config_yml['google_storage_ids']['owners']
40
+ @gsid_editors = config_yml['google_storage_ids']['editors'] if config_yml['google_storage_ids']['editors']
41
+ @gsid_team = config_yml['google_storage_ids']['team'] if config_yml['google_storage_ids']['team']
42
+ end
43
+
44
+ #TODO - make redirect_uri's support multiple urls
45
+ @redirect_uri = config_yml['web_applications']['redirect_uris']
46
+ #TODO - maybe add support for API v1 as well... but probably not..
47
+ @api_version = options[:x_goog_api_version] ? options[:x_goog_api_version] : 2
48
+ @debug = options[:debug]
49
+ @timeout = options[:timeout]
50
+ @host = options[:host] ? options[:host] : 'commondatastorage.googleapis.com'
51
+ end
52
+
53
+ def google_storage_id(id)
54
+ case id
55
+ when :you
56
+ @gsid_you
57
+ when :owners
58
+ @gsid_owners
59
+ when :editors
60
+ @gsid_editors
61
+ when :team
62
+ @gsid_team
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def get(bucket, path, options={})
69
+ http_request(Net::HTTP::Get, bucket, path, options)
70
+ end
71
+
72
+ def put(bucket, path, options={})
73
+ http_request(Net::HTTP::Put, bucket, path, options)
74
+ end
75
+
76
+ def delete(bucket, path, options={})
77
+ http_request(Net::HTTP::Delete, bucket, path, options)
78
+ end
79
+
80
+ def head(bucket, path, options={})
81
+ http_request(Net::HTTP::Head, bucket, path, options)
82
+ end
83
+
84
+ def post_request(host, path, token, options={})
85
+ params = options.delete(:params) || {}
86
+ headers = options.delete(:headers) || {}
87
+ params[:"client_id"] = @client_id
88
+ params[:"client_secret"] = @client_secret
89
+ params[:"grant_type"] = options['grant_type']
90
+
91
+ case options['grant_type']
92
+ when 'authorization_code'
93
+ params[:"code"] = token
94
+ params[:"redirect_uri"] = @redirect_uri
95
+ when 'refresh_token'
96
+ params[:"refresh_token"] = token
97
+ end
98
+
99
+ construct_post_request(host, path, headers, params, options)
100
+ end
101
+
102
+ def http_request(method, bucket, path, options={})
103
+ host = bucket ? "#{bucket}.#{@host}" : @host
104
+ params = options.delete(:params) || {}
105
+ headers = options.delete(:headers) || {}
106
+ construct_http_request(host, path, method, headers, params, options)
107
+ end
108
+
109
+ end
110
+ end
111
+
@@ -0,0 +1,107 @@
1
+
2
+ require 'digest/md5'
3
+
4
+ module GoogleStorage
5
+ class Client
6
+
7
+ def get_object(bucket, filename, options={})
8
+ filename.gsub!(/^\//, "")
9
+ resp = get(bucket, "/#{filename}", options)
10
+ return Crack::XML.parse(resp.body) unless resp.code == "200"
11
+ resp_obj = {}
12
+ if options[:write_to_file]
13
+ begin
14
+ File.open(options[:write_to_file], 'wb') {|f| f.write(resp.body) }
15
+ rescue Exception => msg
16
+ return {:error => msg}
17
+ end
18
+ resp_obj.clear
19
+ resp_obj[:success] = true
20
+ resp_obj[:message] = "File created"
21
+ resp_obj[:path_to_file] = options[:write_to_file]
22
+ return resp_obj
23
+ end
24
+ resp_obj[:success] = true
25
+ resp_obj[:filename] = filename
26
+ resp_obj[:body] = resp.body
27
+ resp_obj[:type] = resp.header["content-type"]
28
+ resp_obj[:size] = resp.header["content-length"]
29
+
30
+ return resp_obj
31
+ end
32
+
33
+ def put_object(bucket, filename, options={})
34
+ filename.gsub!(/^\//, "")
35
+ if options[:path_to_file]
36
+ begin
37
+ uploaded_file = File.open(options[:path_to_file])
38
+ if uploaded_file.respond_to?(:get_input_stream)
39
+ uploaded_file.get_input_stream { |io| @data = io.read }
40
+ else
41
+ uploaded_file.binmode
42
+ @data = uploaded_file.read
43
+ end
44
+ rescue Exception => msg
45
+ return {:error => msg}
46
+ end
47
+ options[:data] = @data
48
+ end
49
+ resp = put(bucket, "/#{filename}", options)
50
+ public_file = (options[:x_goog_acl] && options[:x_goog_acl].match(/public/))
51
+ return Crack::XML.parse(resp.body) unless resp.code == "200"
52
+ resp_obj = {}
53
+ resp_obj[:success] = true
54
+ resp_obj[:message] = "Object added successfully"
55
+ resp_obj[:filename] = filename
56
+ resp_obj[:content_type] = options[:content_type]
57
+ resp_obj[:url] = public_file ? "http://#{@host}/#{bucket}/#{filename}" : \
58
+ "https://sandbox.google.com/storage/#{bucket}/#{filename}"
59
+ resp_obj[:url_type] = public_file ? "public" : "private"
60
+ return resp_obj
61
+ end
62
+
63
+ def list_acls_for_object(bucket, filename, options={})
64
+ filename.gsub!(/^\//, "")
65
+ resp = get(bucket, "/#{filename}?acl", options)
66
+ resp_obj = Crack::XML.parse(resp.body)
67
+ if resp_obj["AccessControlList"]
68
+ resp_obj[:success] = true
69
+ resp_obj[:object_name] = filename
70
+ resp_obj[:acl] = resp_obj["AccessControlList"]
71
+ resp_obj[:raw] = Crack::XML.parse(resp.body)
72
+ resp_obj.each_key {|key| resp_obj.delete(key) unless key == :success || key == :object_name || key == :acl || key == :raw }
73
+ end
74
+ return resp_obj
75
+ end
76
+
77
+ alias :object_acls :list_acls_for_object
78
+
79
+ def head_object(bucket, filename, options={})
80
+ filename.gsub!(/^\//, "")
81
+ resp = head(bucket, "/#{filename}", options)
82
+ return resp.header unless resp.code == "200"
83
+ resp_obj = {}
84
+ resp_obj[:success] = true
85
+ resp_obj[:filename] = filename
86
+ resp_obj[:last_modified] = resp.header['last-modified'] if resp.header['last-modified']
87
+ resp_obj[:etag] = resp.header['etag'] if resp.header['etag']
88
+ resp_obj[:content_length] = resp.header['content-length'] if resp.header['content-length']
89
+ resp_obj[:content_type] = resp.header['content-type'] if resp.header['content-type']
90
+ resp_obj[:cache_control] = resp.header['cache-control'] if resp.header['cache-control']
91
+ resp_obj[:date] = resp.header['date'] if resp.header['date']
92
+ return resp_obj
93
+ end
94
+
95
+ alias :object_head :head_object
96
+
97
+ def delete_object(bucket, filename, options={})
98
+ filename.gsub!(/^\//, "")
99
+ resp = delete(bucket, "/#{filename}", options)
100
+ return Crack::XML.parse(resp.body) unless resp.code == "204"
101
+ resp_obj = {}
102
+ resp_obj[:success] = true
103
+ resp_obj[:message] = "Object deleted successfully"
104
+ return resp_obj
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,81 @@
1
+ require 'net/https'
2
+ require 'cgi'
3
+
4
+ module GoogleStorage
5
+ class Client
6
+
7
+ def construct_post_request(host, path, headers={}, params={}, options={})
8
+ headers["Host"] = host
9
+ headers["Date"] = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
10
+ headers["Content-Type"] = 'application/x-www-form-urlencoded'
11
+ headers["Content-Length"] = "0"
12
+ Crack::JSON.parse(_post_http_request(host, path, params, headers, options[:data]))
13
+ end
14
+
15
+ def construct_http_request(host, path, method, headers={}, params={}, options={})
16
+ raise "\nYou need to acquire a refresh_token before you can make requests to the Google API\n" unless @refresh_token
17
+ headers["Host"] = host
18
+ headers["Date"] = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
19
+ headers["Content-Type"] = options[:content_type] ? options[:content_type] : 'application/x-www-form-urlencoded'
20
+ headers["Content-Length"] = (options[:data] ? options[:data].size : 0).to_s
21
+ headers["x-goog-api-version"] = @api_version
22
+ headers["x-goog-project-id"] = @project_id if options[:send_goog_project_id]
23
+ headers["Authorization"] = 'OAuth ' + self.refresh_access_token(@refresh_token)["access_token"]
24
+ param_string = params.empty? ? '' : '?' + params_to_data_string(params)
25
+ headers["Range"] = options[:range] if options[:range]
26
+ headers["If-Match"] = options[:filename] if options[:filename]
27
+ headers["If-Modified-Since"] = options[:if_modified_since] if options[:if_modified_since]
28
+ headers["If-None-Match"] = options[:if_none_match] if options[:if_none_match]
29
+ headers["If-Unmodified-Since"]= options[:if_modified_since] if options[:if_modified_since]
30
+ headers["Content-MD5"] = options[:md5] if options[:md5]
31
+ headers["x-goog-acl"] = options[:x_goog_acl] if options[:x_goog_acl]
32
+
33
+ _http_request(host, path, method, headers, param_string, options[:data])
34
+ end
35
+
36
+ private
37
+ def _post_http_request(host, path, params, headers, data=nil)
38
+ http = Net::HTTP.new(host, 443)
39
+ http.use_ssl = true
40
+ http.set_debug_output $stderr if @debug
41
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
42
+
43
+ data ||= params_to_data_string(params)
44
+ resp = http.post(path, data, headers)
45
+
46
+ return resp.body
47
+ end
48
+
49
+
50
+ def _http_request(host, path, method, headers, param_string, data=nil)
51
+ http = Net::HTTP.new(host, 443)
52
+ http.use_ssl = true
53
+ http.set_debug_output $stderr if @debug
54
+ http.read_timeout = @timeout ? @timeout : 15
55
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
+
57
+ req = method.new(path + param_string)
58
+ headers.each do |key, value|
59
+ req[key.to_s] = value
60
+ end
61
+
62
+ response = http.start { http.request(req, data) }
63
+ return response
64
+ rescue Timeout::Error
65
+ $stderr.puts "Timeout accessing #{path}: #{$!}"
66
+ nil
67
+ rescue
68
+ $stderr.puts "Error accessing #{path}: #{$!}"
69
+ nil
70
+ end
71
+
72
+ def params_to_data_string(params)
73
+ return "" if params.empty?
74
+ esc_params = params.collect do |p|
75
+ encoded = (CGI::escape(p[0].to_s) + "=" + CGI::escape(p[1].to_s))
76
+ encoded.gsub('+', '%20')
77
+ end
78
+ "#{esc_params.join('&')}"
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,31 @@
1
+ module GoogleStorage
2
+ class Client
3
+
4
+ def authorization_url(scope)
5
+ scope_url = case scope
6
+ when :read_only
7
+ 'https://www.googleapis.com/auth/devstorage.read_only'
8
+ when :read_write
9
+ 'https://www.googleapis.com/auth/devstorage.read_write'
10
+ when :full_control
11
+ 'https://www.googleapis.com/auth/devstorage.full_control'
12
+ else
13
+ 'https://www.google.com/m8/feeds/'
14
+ end
15
+ "https://accounts.google.com/o/oauth2/auth?client_id=#{@client_id}&redirect_uri=#{@redirect_uri}&scope=#{scope_url}&response_type=code"
16
+ end
17
+
18
+ def acquire_refresh_token(token, options={})
19
+ options['grant_type'] = 'authorization_code'
20
+ response = post_request('accounts.google.com', '/o/oauth2/token', token, options)
21
+ return response["refresh_token"] if response["refresh_token"]
22
+ "Failed to acquire a refresh token. Something went wrong. Try getting a new Auth code."
23
+ end
24
+
25
+ def refresh_access_token(token, options={})
26
+ options['grant_type'] = 'refresh_token'
27
+ post_request('accounts.google.com', '/o/oauth2/token', token, options)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module GoogleStorage
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,9 @@
1
+
2
+ require 'crack'
3
+ require 'google_storage/client'
4
+
5
+ module GoogleStorage
6
+
7
+
8
+ end
9
+
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_storage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Lucas Hills
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-24 00:00:00.000000000 +10:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: crack
17
+ requirement: &9643716 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *9643716
26
+ description: A Ruby client library for using the new Google Storage API v2 using OAuth2.0
27
+ email:
28
+ - lucas@lucashills.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files:
32
+ - README.textile
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - README.textile
37
+ - Rakefile
38
+ - examples/examples.rb
39
+ - google_storage.gemspec
40
+ - lib/generators/google_storage/install/install_generator.rb
41
+ - lib/generators/templates/google_storage.rake
42
+ - lib/generators/templates/google_storage.yml
43
+ - lib/google_storage.rb
44
+ - lib/google_storage/bucket.rb
45
+ - lib/google_storage/client.rb
46
+ - lib/google_storage/object.rb
47
+ - lib/google_storage/request.rb
48
+ - lib/google_storage/token.rb
49
+ - lib/google_storage/version.rb
50
+ has_rdoc: true
51
+ homepage: https://github.com/2potatocakes/google_storage
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.6.2
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Google Storage for Developers is a RESTful service for storing and accessing
75
+ your data on Google's infrastructure
76
+ test_files: []