Merge pull request #52 from jeffposnick/master
Added support for caching OAuth 2 credentials to disk
This commit is contained in:
		
						commit
						ef4e924a5c
					
				| 
						 | 
					@ -0,0 +1,87 @@
 | 
				
			||||||
 | 
					# Copyright 2013 Google Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require 'json'
 | 
				
			||||||
 | 
					require 'signet/oauth_2/client'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Google
 | 
				
			||||||
 | 
					  class APIClient
 | 
				
			||||||
 | 
					    ##
 | 
				
			||||||
 | 
					    # Represents cached OAuth 2 tokens stored on local disk in a
 | 
				
			||||||
 | 
					    # JSON serialized file. Meant to resemble the serialized format
 | 
				
			||||||
 | 
					    # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    class FileStorage
 | 
				
			||||||
 | 
					      # @return [String] Path to the credentials file.
 | 
				
			||||||
 | 
					      attr_accessor :path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # @return [Signet::OAuth2::Client] Path to the credentials file.
 | 
				
			||||||
 | 
					      attr_reader :authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ##
 | 
				
			||||||
 | 
					      # Initializes the FileStorage object.
 | 
				
			||||||
 | 
					      #
 | 
				
			||||||
 | 
					      # @param [String] path
 | 
				
			||||||
 | 
					      #    Path to the credentials file.
 | 
				
			||||||
 | 
					      def initialize(path)
 | 
				
			||||||
 | 
					        @path = path
 | 
				
			||||||
 | 
					        self.load_credentials
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ##
 | 
				
			||||||
 | 
					      # Attempt to read in credentials from the specified file.
 | 
				
			||||||
 | 
					      def load_credentials
 | 
				
			||||||
 | 
					        if File.exist? self.path
 | 
				
			||||||
 | 
					          File.open(self.path, 'r') do |file|
 | 
				
			||||||
 | 
					            cached_credentials = JSON.load(file)
 | 
				
			||||||
 | 
					            @authorization = Signet::OAuth2::Client.new(cached_credentials)
 | 
				
			||||||
 | 
					            @authorization.issued_at = Time.at(cached_credentials['issued_at'])
 | 
				
			||||||
 | 
					            if @authorization.expired?
 | 
				
			||||||
 | 
					              @authorization.fetch_access_token!
 | 
				
			||||||
 | 
					              self.write_credentials
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ##
 | 
				
			||||||
 | 
					      # Write the credentials to the specified file.
 | 
				
			||||||
 | 
					      #
 | 
				
			||||||
 | 
					      # @param [Signet::OAuth2::Client] authorization
 | 
				
			||||||
 | 
					      #    Optional authorization instance. If not provided, the authorization
 | 
				
			||||||
 | 
					      #    already associated with this instance will be written.
 | 
				
			||||||
 | 
					      def write_credentials(authorization=nil)
 | 
				
			||||||
 | 
					        @authorization = authorization unless authorization.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unless @authorization.refresh_token.nil?
 | 
				
			||||||
 | 
					          hash = {}
 | 
				
			||||||
 | 
					          %w'access_token
 | 
				
			||||||
 | 
					           authorization_uri
 | 
				
			||||||
 | 
					           client_id
 | 
				
			||||||
 | 
					           client_secret
 | 
				
			||||||
 | 
					           expires_in
 | 
				
			||||||
 | 
					           refresh_token
 | 
				
			||||||
 | 
					           token_credential_uri'.each do |var|
 | 
				
			||||||
 | 
					            hash[var] = @authorization.instance_variable_get("@#{var}")
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					          hash['issued_at'] = @authorization.issued_at.to_i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          File.open(self.path, 'w', 0600) do |file|
 | 
				
			||||||
 | 
					            file.write(hash.to_json)
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -77,9 +77,13 @@ module Google
 | 
				
			||||||
      ##
 | 
					      ##
 | 
				
			||||||
      # Request authorization. Opens a browser and waits for response.
 | 
					      # Request authorization. Opens a browser and waits for response.
 | 
				
			||||||
      #
 | 
					      #
 | 
				
			||||||
 | 
					      # @param [Google::APIClient::FileStorage] storage
 | 
				
			||||||
 | 
					      #  Optional object that responds to :write_credentials, used to serialize
 | 
				
			||||||
 | 
					      #  the OAuth 2 credentials after completing the flow.
 | 
				
			||||||
 | 
					      #
 | 
				
			||||||
      # @return [Signet::OAuth2::Client]
 | 
					      # @return [Signet::OAuth2::Client]
 | 
				
			||||||
      #  Authorization instance, nil if user cancelled.
 | 
					      #  Authorization instance, nil if user cancelled.
 | 
				
			||||||
      def authorize
 | 
					      def authorize(storage=nil)
 | 
				
			||||||
        auth = @authorization
 | 
					        auth = @authorization
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        server = WEBrick::HTTPServer.new(
 | 
					        server = WEBrick::HTTPServer.new(
 | 
				
			||||||
| 
						 | 
					@ -103,6 +107,9 @@ module Google
 | 
				
			||||||
        Launchy.open(auth.authorization_uri.to_s)
 | 
					        Launchy.open(auth.authorization_uri.to_s)
 | 
				
			||||||
        server.start
 | 
					        server.start
 | 
				
			||||||
        if @authorization.access_token
 | 
					        if @authorization.access_token
 | 
				
			||||||
 | 
					          if storage.respond_to?(:write_credentials)
 | 
				
			||||||
 | 
					            storage.write_credentials(@authorization)
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
          return @authorization
 | 
					          return @authorization
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          return nil
 | 
					          return nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue