Class: GoogleDrive
- Inherits:
-
Object
- Object
- GoogleDrive
- Defined in:
- lib/google_drive.rb
Overview
Convience wrapper for Google Drive
You can override the location of the client secrets and oauth2 JSON files with the environment variables GOOGLE_CLIENT_SECRETS and GOOGLE_DRIVE_OAUTH.
If you plan to run Middleman on a server, you can use Google’s server to server authentication. This will kick in if you define the environment variables GOOGLE_OAUTH_PERSON, GOOGLE_OAUTH_ISSUER and either GOOGLE_OAUTH_KEYFILE or GOOGLE_OAUTH_PRIVATE_KEY.
Defined Under Namespace
Classes: ConfigurationError, CreateError, DoesNotExist, GoogleDriveError
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Google API Client object.
Instance Method Summary collapse
-
#clear_auth ⇒ Object
Delete cached credentials.
-
#copy(file_id, title = nil, visibility = :private) ⇒ Hash
(also: #copy_doc)
Make a copy of a Google Drive file.
-
#do_auth ⇒ Object
Authenticate with Google and create the @client object.
-
#export(file_id, type) ⇒ String
Export a file Returns the file contents.
-
#export_to_file(file_id, type, filename = nil) ⇒ String
Export a file and save to disk Returns the local path to the file.
-
#find(file_id) ⇒ Hash
Find a Google Drive file Takes the key of a Google Drive file and returns a hash of meta data.
-
#initialize ⇒ GoogleDrive
constructor
Constructor.
-
#load_microcopy(table) ⇒ Hash
Take a two-dimensional array from a spreadsheet and create a hash.
-
#load_table(table) ⇒ Array<Hash>
Take a two-dimensional array from a spreadsheet and create an array of hashes.
-
#local? ⇒ Boolean
Returns true if we’re using local oauth2 (like on your computer).
-
#mime_for(extension) ⇒ String?
Get the mime type from a file extension.
-
#prepare_spreadsheet(filename) ⇒ Hash
Parse a spreadsheet Reduces the spreadsheet to a no-frills hash, suitable for serializing and passing around.
-
#server? ⇒ Boolean
Returns true if we’re using a private key to autheticate (like on a server).
Constructor Details
#initialize ⇒ GoogleDrive
Constructor. Loads all params from envionment variables.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/google_drive.rb', line 23 def initialize @credentials = ENV['GOOGLE_DRIVE_OAUTH'] || File.( '~/.google_drive_oauth2.json') @client_secrets = ENV['GOOGLE_CLIENT_SECRETS'] || File.( '~/.google_client_secrets.json') @person = ENV['GOOGLE_OAUTH_PERSON'] @issuer = ENV['GOOGLE_OAUTH_ISSUER'] @key_path = ENV['GOOGLE_OAUTH_KEYFILE'] @private_key = ENV['GOOGLE_OAUTH_PRIVATE_KEY'] # try to read the file, # throw errors if not readable or not found if @key_path @key = Google::APIClient::KeyUtils.load_from_pkcs12( @key_path, 'notasecret') elsif @private_key @key = OpenSSL::PKey::RSA.new( @private_key, 'notasecret') end @_files = {} @_spreadsheets = {} do_auth end |
Instance Attribute Details
#client ⇒ Object (readonly)
Google API Client object
20 21 22 |
# File 'lib/google_drive.rb', line 20 def client @client end |
Instance Method Details
#clear_auth ⇒ Object
Delete cached credentials
245 246 247 |
# File 'lib/google_drive.rb', line 245 def clear_auth File.delete @credentials if @key.nil? end |
#copy(file_id, title = nil, visibility = :private) ⇒ Hash Also known as: copy_doc
Make a copy of a Google Drive file
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/google_drive.rb', line 134 def copy(file_id, title = nil, visibility = :private) drive = @client.discovered_api('drive', 'v2') if title.nil? copied_file = drive.files.copy.request_schema.new else copied_file = drive.files.copy.request_schema.new('title' => title) end cp_resp = @client.execute( api_method: drive.files.copy, body_object: copied_file, parameters: { fileId: file_id, visibility: visibility.to_s.upcase }) if cp_resp.error? fail CreateError, cp_resp. else return { id: cp_resp.data['id'], url: cp_resp.data['alternateLink'] } end end |
#do_auth ⇒ Object
Authenticate with Google and create the @client object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/google_drive.rb', line 250 def do_auth if local? @client = Google::APIClient.new( application_name: 'Middleman', application_version: Middleman::GoogleDrive::VERSION ) begin file_storage = Google::APIClient::FileStorage.new(@credentials) rescue URI::InvalidURIError File.delete @credentials file_storage = Google::APIClient::FileStorage.new(@credentials) end if file_storage..nil? unless File.exist? @client_secrets fail ConfigurationError, 'You need to create a client_secrets.json file and save it to ~/.google_client_secrets.json.' end puts "\nPlease login via your web browser. We opened the tab for you...\n\n MSG\n client_secrets = Google::APIClient::ClientSecrets.load(@client_secrets)\n flow = Google::APIClient::InstalledAppFlow.new(\n client_id: client_secrets.client_id,\n client_secret: client_secrets.client_secret,\n scope: ['https://www.googleapis.com/auth/drive']\n )\n @client.authorization = flow.authorize(file_storage)\n else\n @client.authorization = file_storage.authorization\n end\n else\n @client = Google::APIClient.new(\n application_name: 'Middleman',\n application_version: Middleman::GoogleDrive::VERSION,\n authorization: Signet::OAuth2::Client.new(\n token_credential_uri: 'https://accounts.google.com/o/oauth2/token',\n audience: 'https://accounts.google.com/o/oauth2/token',\n person: @person,\n issuer: @issuer,\n signing_key: @key,\n scope: ['https://www.googleapis.com/auth/drive']\n )\n )\n @client.authorization.fetch_access_token!\n end\n nil\nend\n" |
#export(file_id, type) ⇒ String
Export a file Returns the file contents
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/google_drive.rb', line 81 def export(file_id, type) list_resp = find(file_id) # decide which mimetype we want mime = mime_for(type).content_type # Grab the export url. if list_resp['exportLinks'] && list_resp['exportLinks'][mime] uri = list_resp['exportLinks'][mime] else raise "Google doesn't support exporting file id #{file_id} to #{type}" end # get the export get_resp = @client.execute(uri: uri) # die if there's an error fail GoogleDriveError, get_resp. if get_resp.error? # contents get_resp.body end |
#export_to_file(file_id, type, filename = nil) ⇒ String
Export a file and save to disk Returns the local path to the file
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/google_drive.rb', line 111 def export_to_file(file_id, type, filename = nil) contents = export(file_id, type) if filename.nil? # get a temporary file. The export is binary, so open the tempfile in # write binary mode Tempfile.create( ['googledoc', ".#{type}"], binmode: mime_for(type.to_s).binary?) do |fp| filename = fp.path fp.write contents end else open(filename, 'wb') { |fp| fp.write contents } end filename end |
#find(file_id) ⇒ Hash
Find a Google Drive file Takes the key of a Google Drive file and returns a hash of meta data. The returned hash is formatted as a Google Drive resource.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/google_drive.rb', line 59 def find(file_id) return @_files[file_id] unless @_files[file_id].nil? drive = @client.discovered_api('drive', 'v2') # get the file metadata resp = @client.execute( api_method: drive.files.get, parameters: { fileId: file_id }) # die if there's an error fail GoogleDriveError, resp. if resp.error? @_files[file_id] = resp.data end |
#load_microcopy(table) ⇒ Hash
Take a two-dimensional array from a spreadsheet and create a hash. The first column is used as the key, and the second column is the value. If the key occurs more than once, the value becomes an array to hold all the values associated with the key.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/google_drive.rb', line 197 def load_microcopy(table) data = {} table.each_with_index do |row, i| next if i == 0 # skip the header row # Did we already create this key? if data.keys.include? row[0] # if the key name is reused, create an array with all the entries if data[row[0]].is_a? Array data[row[0]] << row[1] else data[row[0]] = [data[row[0]], row[1]] end else # add this row's key and value to the hash data[row[0]] = row[1] end end data end |
#load_table(table) ⇒ Array<Hash>
Take a two-dimensional array from a spreadsheet and create an array of hashes.
221 222 223 224 225 226 227 228 |
# File 'lib/google_drive.rb', line 221 def load_table(table) return [] if table.length < 2 header = table.shift # Get the header row table.map do |row| # zip headers with current row, convert it to a hash header.zip(row).to_h unless row.nil? end end |
#local? ⇒ Boolean
Returns true if we’re using local oauth2 (like on your computer).
240 241 242 |
# File 'lib/google_drive.rb', line 240 def local? @key.nil? end |
#mime_for(extension) ⇒ String?
Get the mime type from a file extension
159 160 161 |
# File 'lib/google_drive.rb', line 159 def mime_for(extension) MIME::Types.of(extension.to_s).first end |
#prepare_spreadsheet(filename) ⇒ Hash
Parse a spreadsheet Reduces the spreadsheet to a no-frills hash, suitable for serializing and passing around.
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/google_drive.rb', line 170 def prepare_spreadsheet(filename) # open the file with RubyXL xls = RubyXL::Parser.parse(filename) data = {} xls.worksheets.each do |sheet| title = sheet.sheet_name # if the sheet is called microcopy, copy or ends with copy, we assume # the first column contains keys and the second contains values. # Like tarbell. if %w(microcopy copy).include?(title.downcase) || title.downcase =~ /[ -_]copy$/ data[title] = load_microcopy(sheet.extract_data) else # otherwise parse the sheet into a hash data[title] = load_table(sheet.extract_data) end end return data end |
#server? ⇒ Boolean
Returns true if we’re using a private key to autheticate (like on a server).
234 235 236 |
# File 'lib/google_drive.rb', line 234 def server? !local? end |