paperclip-googledrive 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ivan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # PaperclipGoogledrive
2
+ --- WORK IN PROGRESS ---
3
+
4
+ PaperclipGoogledrive is a gem that extends paperclip storage for Google Drive.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'paperclip-googledrive'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install paperclip-googledrive
19
+
20
+ ## Usage
21
+
22
+ May be available soon.
23
+
24
+ Add to class
25
+ has_attach_file method and descript name of attachemnt, set storage to google drive and set credentials and options.
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
@@ -0,0 +1,3 @@
1
+
2
+ require 'paperclip'
3
+ require 'paperclip/google_drive'
@@ -0,0 +1,2 @@
1
+ require "paperclip/storage/google_drive"
2
+ require "paperclip/google_drive/railtie" if defined?(Rails)
@@ -0,0 +1,10 @@
1
+
2
+ module Paperclip
3
+ module GoogleDrive
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load "paperclip/google_drive/tasks.rake"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,50 @@
1
+
2
+ require 'google/api_client'
3
+
4
+ module Paperclip
5
+ module GoogleDrive
6
+ module Rake
7
+ extend self
8
+
9
+ def authorize
10
+ puts 'Enter client ID:'
11
+ client_id = $stdin.gets.chomp
12
+ puts 'Enter client SECRET:'
13
+ client_secret = $stdin.gets.chomp.strip
14
+ puts 'Enter SCOPE:'
15
+ oauth_scope = $stdin.gets.chomp.strip
16
+ puts 'Enter redirect URI:'
17
+ redirect_uri = $stdin.gets.chomp.strip
18
+
19
+ # Create a new API client & load the Google Drive API
20
+ client = Google::APIClient.new
21
+ drive = client.discovered_api('drive', 'v2')
22
+
23
+ client.authorization.client_id = client_id
24
+ client.authorization.client_secret = client_secret
25
+ client.authorization.scope = oauth_scope
26
+ client.authorization.redirect_uri = redirect_uri
27
+
28
+ # Request authorization
29
+ uri = client.authorization.authorization_uri.to_s
30
+ puts "\nGo to this url:"
31
+ puts client.authorization.authorization_uri.to_s
32
+ puts "\n Accept the authorization request from Google in your browser"
33
+
34
+ puts "\n\n\n Google will redirect you to localhost, but just copy the code parameter out of the URL they redirect you to, paste it here and hit enter:\n"
35
+
36
+ code = $stdin.gets.chomp.strip
37
+ client.authorization.code = code
38
+ client.authorization.fetch_access_token!
39
+
40
+ puts "\nAuthorization complete!:\n\n"
41
+ puts "client = Google::APIClient.new"
42
+ puts "client.authorization.client_id = '#{client_id}'"
43
+ puts "client.authorization.client_secret = '#{client_secret}'"
44
+ puts "client.authorization.access_token = '#{client.authorization.access_token}'"
45
+ puts "client.authorization.refresh_token = '#{client.authorization.refresh_token}'"
46
+ puts "\n"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+
2
+ require "paperclip/google_drive/rake"
3
+
4
+ namespace :google_drive do
5
+ desc "Authorize Google Drive account: "
6
+ task :authorize do
7
+ Paperclip::GoogleDrive::Rake.authorize
8
+ end
9
+ end
10
+
@@ -0,0 +1,254 @@
1
+
2
+ require 'active_support/core_ext/hash/keys'
3
+ require 'active_support/inflector/methods'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'yaml'
6
+ require 'erb'
7
+ require 'google/api_client'
8
+
9
+ module Paperclip
10
+
11
+ module Storage
12
+ # * self.extended(base) add instance variable to attachment on call
13
+ # * url return url to show on site with style options
14
+ # * path(style) return title that used to insert file to store or find it in store
15
+ # * public_url_for title return url to file if find by title or url to default image if set
16
+ # * search_for_title(title) take title, search in given folder and if it finds a file, return id of a file or nil
17
+ # * metadata_by_id(file_i get file metadata from store, used to back url or find out value of trashed
18
+ # * exists?(style) check either exists file with title or not
19
+ # * default_image return url to default url if set in option
20
+ # * find_public_folder return id of Public folder, must be in options
21
+ # return id of Public folder, must be in options
22
+ # * file_tit return base pattern of title or custom one set by user
23
+ # * parse_credentials(credenti get credentials from file, hash or path
24
+ # * assert_required_keys check either all ccredentials keys is set
25
+ # * original_extension return extension of file
26
+
27
+ module GoogleDrive
28
+
29
+ def self.extended(base)
30
+ begin
31
+ require 'google-api-client'
32
+ rescue LoadError => e
33
+ e.message << " (You may need to install the google-api-client gem)"
34
+ raise e
35
+ end unless defined?(Google)
36
+
37
+ base.instance_eval do
38
+ @google_drive_credentials = parse_credentials(@options[:google_drive_credentials] || {})
39
+ @google_drive_options = @options[:google_drive_options] || {}
40
+ google_api_client # Force validations of credentials
41
+ end
42
+ end
43
+ #
44
+ def flush_writes
45
+ @queued_for_write.each do |style, file|
46
+ if exists?(path(style))
47
+ raise FileExists, "file \"#{path(style)}\" already exists in your Google Drive"
48
+ else
49
+ #upload(style, file) #style file
50
+ client = google_api_client
51
+ drive = client.discovered_api('drive', 'v2')
52
+ oauth2 = client.discovered_api('oauth2', 'v2')
53
+ result = client.execute!(:api_method => oauth2.userinfo.get)
54
+ client.authorization.access_token = result.request.authorization.access_token
55
+ client.authorization.refresh_token = result.request.authorization.refresh_token
56
+ title, mime_type = title_for_file(style), "#{content_type}"
57
+ parent_id = @google_drive_options[:public_folder_id] # folder_id for Public folder
58
+ metadata = drive.files.insert.request_schema.new({
59
+ 'title' => title, #if it is no extension, that is a folder and another folder
60
+ 'description' => 'paperclip file on google drive',
61
+ 'mimeType' => mime_type })
62
+ if parent_id
63
+ metadata.parents = [{'id' => parent_id}]
64
+ end
65
+ media = Google::APIClient::UploadIO.new( file, mime_type)
66
+ result = client.execute(
67
+ :api_method => drive.files.insert,
68
+ :body_object => metadata,
69
+ :media => media,
70
+ :parameters => {
71
+ 'uploadType' => 'multipart',
72
+ 'alt' => 'json' })
73
+ end
74
+ end
75
+ after_flush_writes
76
+ @queued_for_write = {}
77
+ end
78
+ #
79
+ def flush_deletes
80
+ @queued_for_delete.each do |path|
81
+ Paperclip.log("delete #{path}")
82
+ client = google_api_client
83
+ drive = client.discovered_api('drive', 'v2')
84
+ file_id = search_for_title(path)
85
+ unless file_id.nil?
86
+ folder_id = find_public_folder
87
+ parameters = {'fileId' => file_id,
88
+ 'folder_id' => folder_id }
89
+ result = client.execute(
90
+ :api_method => drive.files.delete,
91
+ :parameters => parameters)
92
+ if result.status != 200
93
+ puts "An error occurred: #{result.data['error']['message']}"
94
+ end
95
+ end
96
+ end
97
+ @queued_for_delete = []
98
+ end
99
+ #
100
+ def google_api_client
101
+ @google_api_client ||= begin
102
+ assert_required_keys
103
+ # Initialize the client & Google+ API
104
+ client = Google::APIClient.new
105
+ client.authorization.client_id = @google_drive_credentials[:client_id]
106
+ client.authorization.client_secret = @google_drive_credentials[:client_secret]
107
+ client.authorization.access_token = @google_drive_credentials[:access_token]
108
+ client.authorization.refresh_token = @google_drive_credentials[:refresh_token]
109
+ client
110
+ end
111
+ end
112
+ #
113
+ def google_drive
114
+ client = google_api_client
115
+ drive = client.discovered_api('drive', 'v2')
116
+ drive
117
+ end
118
+
119
+ def url(*args)
120
+ if present?
121
+ style = args.first.is_a?(Symbol) ? args.first : default_style
122
+ options = args.last.is_a?(Hash) ? args.last : {}
123
+ public_url_for(path(style))
124
+ else
125
+ default_image
126
+ end
127
+ end
128
+
129
+ def path(style)
130
+ title_for_file(style)
131
+ end
132
+
133
+ def title_for_file(style)
134
+ file_name = instance.instance_exec(style, &file_title)
135
+
136
+ style_suffix = (style != default_style ? "_#{style}" : "")
137
+
138
+ if original_extension.present? && file_name =~ /#{original_extension}$/
139
+ file_name.sub(original_extension, "#{style_suffix}#{original_extension}")
140
+ else
141
+ file_name + style_suffix + original_extension.to_s
142
+ end
143
+ end # full title
144
+
145
+ def public_url_for title
146
+ searched_id = search_for_title(title) #return id if any or style
147
+ if searched_id.nil? # it finds some file
148
+ default_image
149
+ else
150
+ metadata = metadata_by_id(searched_id)
151
+ metadata['webContentLink']
152
+ end
153
+ end # url
154
+ # take title, search in given folder and if it finds a file, return id of a file or nil
155
+ def search_for_title(title)
156
+ parameters = {
157
+ 'folderId' => find_public_folder,
158
+ 'q' => "title contains '#{title}'", # full_title
159
+ 'fields' => 'items/id'}
160
+ client = google_api_client
161
+ drive = client.discovered_api('drive', 'v2')
162
+ result = client.execute(:api_method => drive.children.list,
163
+ :parameters => parameters)
164
+ if result.status == 200
165
+ if result.data.items.length > 0
166
+ result.data.items[0]['id']
167
+ elsif result.data.items.length == 0
168
+ nil
169
+ else
170
+ nil
171
+ end
172
+ end
173
+ end # id or nil
174
+
175
+ def metadata_by_id(file_id)
176
+ if file_id.is_a? String
177
+ client = google_api_client
178
+ drive = client.discovered_api('drive', 'v2')
179
+ result = client.execute(
180
+ :api_method => drive.files.get,
181
+ :parameters => {'fileId' => file_id,
182
+ 'fields' => 'title, id, webContentLink, labels/trashed' })
183
+ if result.status == 200
184
+ result.data # data.class # => Hash
185
+ end
186
+ end
187
+ end
188
+
189
+ def exists?(style)
190
+ result_id = search_for_title(path(style))
191
+ if result_id.nil?
192
+ false
193
+ else
194
+ data_hash = metadata_by_id(result_id)
195
+ !data_hash['labels']['trashed'] # if trashed -> not exists
196
+ end
197
+ end
198
+
199
+ def default_image
200
+ if @google_drive_options[:default_url] #if default image is set
201
+ title = @google_drive_options[:default_url]
202
+ searched_id = search_for_title(title) # id
203
+ metadata = metadata_by_id(searched_id) unless searched_id.nil?
204
+ metadata['webContentLink']
205
+ else
206
+ 'No picture' # ---- ?
207
+ end
208
+ end
209
+
210
+ def find_public_folder
211
+ unless @google_drive_options[:public_folder_id]
212
+ raise KeyError, "you must set a Public folder if into options"
213
+ end
214
+ @google_drive_options[:public_folder_id]
215
+ end
216
+ class FileExists < ArgumentError
217
+ end
218
+ private
219
+
220
+ def file_title
221
+ return @google_drive_options[:path] if @google_drive_options[:path] #path: proc
222
+ eval %(proc { |style| "\#{id}_\#{#{name}.original_filename}"})
223
+ end
224
+
225
+ def parse_credentials(credentials)
226
+ result =
227
+ case credentials
228
+ when File
229
+ YAML.load(ERB.new(File.read(credentials.path)).result)
230
+ when String, Pathname
231
+ YAML.load(ERB.new(File.read(credentials)).result)
232
+ when Hash
233
+ credentials
234
+ else
235
+ raise ArgumentError, ":google_drive_credentials are not a path, file, nor a hash"
236
+ end
237
+ result.symbolize_keys #or string keys
238
+ end
239
+ # check either all ccredentials keys is set
240
+ def assert_required_keys
241
+ keys_list = [:client_id, :client_secret, :access_token, :refresh_token]
242
+ keys_list.each do |key|
243
+ @google_drive_credentials.fetch(key)
244
+ end
245
+ end
246
+ # return extension of file
247
+ def original_extension
248
+ File.extname(original_filename)
249
+ end
250
+ end
251
+
252
+ end
253
+
254
+ end
@@ -0,0 +1,3 @@
1
+ module PaperclipGoogleDrive
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #require File.expand_path('../lib/paperclip_googledrive/version', __FILE__)
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "paperclip/version"
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "paperclip-googledrive"
8
+ gem.version = PaperclipGoogleDrive::VERSION
9
+ gem.authors = ['evinsou']
10
+ gem.email = ["evinsou@gmail.com"]
11
+
12
+ gem.summary = %q{Extends Paperclip with Google Drive storage}
13
+ gem.description = %q{paperclip-googledrive extends paperclip support of storage for google drive storage}
14
+ gem.homepage = ""
15
+
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.files = Dir["lib/**/*"] + ["README.md", "LICENSE", "paperclip-googledrive.gemspec"]
18
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+
20
+ gem.require_paths = ["lib"]
21
+ gem.required_ruby_version = ">= 1.9.2"
22
+ gem.license = "MIT"
23
+
24
+ gem.add_dependency "paperclip", "~> 3.4"
25
+ gem.add_dependency 'google-api-client', "~> 0.5"
26
+
27
+ gem.add_development_dependency "rake", ">= 0.9"
28
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paperclip-googledrive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - evinsou
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: paperclip
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.4'
30
+ - !ruby/object:Gem::Dependency
31
+ name: google-api-client
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0.5'
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.5'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0.9'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ description: paperclip-googledrive extends paperclip support of storage for google
63
+ drive storage
64
+ email:
65
+ - evinsou@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/paperclip-googledrive.rb
71
+ - lib/paperclip/google_drive.rb
72
+ - lib/paperclip/storage/google_drive.rb
73
+ - lib/paperclip/version.rb
74
+ - lib/paperclip/google_drive/railtie.rb
75
+ - lib/paperclip/google_drive/rake.rb
76
+ - lib/paperclip/google_drive/tasks.rake
77
+ - README.md
78
+ - LICENSE
79
+ - paperclip-googledrive.gemspec
80
+ homepage: ''
81
+ licenses:
82
+ - MIT
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: 1.9.2
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.24
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Extends Paperclip with Google Drive storage
105
+ test_files: []