google_storage 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: []