diff --git a/.rubocop.yml b/.rubocop.yml index 14cbc8f..f573ff9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,30 +1,11 @@ +inherit_gem: + google-style: google-style.yml + AllCops: Exclude: - "spec/**/*" - "Rakefile" - -Metrics/AbcSize: - Max: 25 -Metrics/BlockLength: - Exclude: - - "googleauth.gemspec" -Metrics/CyclomaticComplexity: - Max: 8 -Metrics/MethodLength: - Max: 20 -Metrics/ModuleLength: - Max: 150 Metrics/ClassLength: - Enabled: false -Layout/IndentHeredoc: - Enabled: false -Style/FormatString: - Enabled: false -Style/GuardClause: - Enabled: false -Style/PercentLiteralDelimiters: # Contradicting rule - Enabled: false -Style/StringLiterals: - EnforcedStyle: double_quotes -Style/SymbolArray: # Undefined syntax in Ruby 1.9.3 - Enabled: false + Max: 110 +Metrics/ModuleLength: + Max: 105 diff --git a/Gemfile b/Gemfile index 9bc8d98..136e757 100755 --- a/Gemfile +++ b/Gemfile @@ -8,12 +8,12 @@ group :development do gem "coveralls", "~> 0.7" gem "fakefs", "~> 0.6" gem "fakeredis", "~> 0.5" + gem "google-style", "~> 0.2" gem "logging", "~> 2.0" gem "rack-test", "~> 0.6" gem "rake", "~> 10.0" gem "redis", "~> 3.2" gem "rspec", "~> 3.0" - gem "rubocop", ">= 0.41", "< 0.50" gem "simplecov", "~> 0.9" gem "sinatra" gem "webmock", "~> 1.21" diff --git a/Rakefile b/Rakefile index 64462b2..2d9b76b 100755 --- a/Rakefile +++ b/Rakefile @@ -1,20 +1,20 @@ # -*- ruby -*- -require 'rspec/core/rake_task' -require 'rubocop/rake_task' -require 'bundler/gem_tasks' +require "rspec/core/rake_task" +require "rubocop/rake_task" +require "bundler/gem_tasks" -desc 'Run Rubocop to check for style violations' +desc "Run Rubocop to check for style violations" RuboCop::RakeTask.new -desc 'Run rake task' -RSpec::Core::RakeTask.new(:spec) +desc "Run rake task" +RSpec::Core::RakeTask.new :spec -desc 'Does rubocop lint and runs the specs' -task all: [:rubocop, :spec] +desc "Does rubocop lint and runs the specs" +task all: %i[rubocop spec] task default: :all -task :release, :tag do |t, args| +task :release, :tag do |_t, args| tag = args[:tag] raise "You must provide a tag to release." if tag.nil? @@ -28,9 +28,11 @@ task :release, :tag do |t, args| api_token = ENV["RUBYGEMS_API_TOKEN"] require "gems" - ::Gems.configure do |config| - config.key = api_token - end if api_token + if api_token + ::Gems.configure do |config| + config.key = api_token + end + end Bundler.with_clean_env do sh "rm -rf pkg" @@ -41,9 +43,9 @@ task :release, :tag do |t, args| path_to_be_pushed = "pkg/#{version}.gem" if File.file? path_to_be_pushed begin - ::Gems.push(File.new path_to_be_pushed) + ::Gems.push File.new(path_to_be_pushed) puts "Successfully built and pushed googleauth for version #{version}" - rescue => e + rescue StandardError => e puts "Error while releasing googleauth version #{version}: #{e.message}" end else @@ -53,10 +55,10 @@ end namespace :kokoro do task :load_env_vars do - service_account = "#{ENV["KOKORO_GFILE_DIR"]}/service-account.json" + service_account = "#{ENV['KOKORO_GFILE_DIR']}/service-account.json" ENV["GOOGLE_APPLICATION_CREDENTIALS"] = service_account - filename = "#{ENV["KOKORO_GFILE_DIR"]}/env_vars.json" - env_vars = JSON.parse(File.read(filename)) + filename = "#{ENV['KOKORO_GFILE_DIR']}/env_vars.json" + env_vars = JSON.parse File.read(filename) env_vars.each { |k, v| ENV[k] = v } end @@ -64,8 +66,8 @@ namespace :kokoro do version = "0.1.0" Bundler.with_clean_env do version = `bundle exec gem list` - .split("\n").select { |line| line.include? "googleauth" } - .first.split("(").last.split(")").first || "0.1.0" + .split("\n").select { |line| line.include? "googleauth" } + .first.split("(").last.split(")").first || "0.1.0" end Rake::Task["kokoro:load_env_vars"].invoke Rake::Task["release"].invoke "v/#{version}" @@ -79,4 +81,4 @@ def header str, token = "#" puts "#{token * 3} #{str} #{token * 3}" puts token * line_length puts "" -end \ No newline at end of file +end diff --git a/googleauth.gemspec b/googleauth.gemspec index 2f5fbbc..5605b94 100755 --- a/googleauth.gemspec +++ b/googleauth.gemspec @@ -1,7 +1,7 @@ # -*- ruby -*- # encoding: utf-8 -$LOAD_PATH.push File.expand_path("../lib", __FILE__) +$LOAD_PATH.push File.expand_path("lib", __dir__) require "googleauth/version" Gem::Specification.new do |gem| @@ -18,10 +18,10 @@ Gem::Specification.new do |gem| https://developers.google.com/accounts/docs/application-default-credentials DESCRIPTION - gem.files = `git ls-files`.split("\n") - gem.test_files = `git ls-files -- spec/*`.split("\n") + gem.files = `git ls-files`.split "\n" + gem.test_files = `git ls-files -- spec/*`.split "\n" gem.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f| - File.basename(f) + File.basename f end gem.require_paths = ["lib"] gem.platform = Gem::Platform::RUBY diff --git a/lib/googleauth/application_default.rb b/lib/googleauth/application_default.rb index 550aa1e..4a5e3a2 100644 --- a/lib/googleauth/application_default.rb +++ b/lib/googleauth/application_default.rb @@ -34,11 +34,13 @@ module Google # Module Auth provides classes that provide Google-specific authorization # used to access Google APIs. module Auth - NOT_FOUND_ERROR = < "Google" } - resp = c.get(COMPUTE_AUTH_TOKEN_URI, nil, headers) + resp = c.get COMPUTE_AUTH_TOKEN_URI, nil, headers case resp.status when 200 Signet::OAuth2.parse_credentials(resp.body, resp.headers["content-type"]) when 404 - raise(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR) + raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR else msg = "Unexpected error code #{resp.status}" \ "#{UNEXPECTED_ERROR_SUFFIX}" - raise(Signet::AuthorizationError, msg) + raise Signet::AuthorizationError, msg end end end diff --git a/lib/googleauth/credentials.rb b/lib/googleauth/credentials.rb index 5eb5fae..f30dd6b 100644 --- a/lib/googleauth/credentials.rb +++ b/lib/googleauth/credentials.rb @@ -27,8 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, MethodLength - require "forwardable" require "json" require "signet/oauth_2/client" @@ -56,7 +54,8 @@ module Google :token_credential_uri, :audience, :scope, :issuer, :signing_key, :updater_proc - def initialize(keyfile, options = {}) + # rubocop:disable Metrics/AbcSize + def initialize keyfile, options = {} scope = options[:scope] verify_keyfile_provided! keyfile @project_id = options["project_id"] || options["project"] @@ -79,12 +78,13 @@ module Google @project_id ||= CredentialsLoader.load_gcloud_project_id @client.fetch_access_token! end + # rubocop:enable Metrics/AbcSize # Returns the default credentials checking, in this order, the path env # evironment variables, json environment variables, default paths. If the # previously stated locations do not contain keyfile information, # this method defaults to use the application default. - def self.default(options = {}) + def self.default options = {} # First try to find keyfile file from environment variables. client = from_path_vars options @@ -99,7 +99,7 @@ module Google client end - def self.from_path_vars(options) + def self.from_path_vars options self::PATH_ENV_VARS .map { |v| ENV[v] } .compact @@ -110,23 +110,21 @@ module Google nil end - def self.from_json_vars(options) + def self.from_json_vars options json = lambda do |v| unless ENV[v].nil? begin JSON.parse ENV[v] - rescue + rescue StandardError nil end end end - self::JSON_ENV_VARS.map(&json).compact.each do |hash| - return new hash, options - end + self::JSON_ENV_VARS.map(&json).compact.each { |hash| return new hash, options } nil end - def self.from_default_paths(options) + def self.from_default_paths options self::DEFAULT_PATHS .select { |p| ::File.file? p } .each do |file| @@ -135,7 +133,7 @@ module Google nil end - def self.from_application_default(options) + def self.from_application_default options scope = options[:scope] || self::SCOPE client = Google::Auth.get_application_default scope new client, options @@ -148,30 +146,30 @@ module Google protected # Verify that the keyfile argument is provided. - def verify_keyfile_provided!(keyfile) + def verify_keyfile_provided! keyfile return unless keyfile.nil? raise "The keyfile passed to Google::Auth::Credentials.new was nil." end # Verify that the keyfile argument is a file. - def verify_keyfile_exists!(keyfile) + def verify_keyfile_exists! keyfile exists = ::File.file? keyfile raise "The keyfile '#{keyfile}' is not a valid file." unless exists end # Initializes the Signet client. - def init_client(keyfile, connection_options = {}) + def init_client keyfile, connection_options = {} client_opts = client_options keyfile Signet::OAuth2::Client.new(client_opts) .configure_connection(connection_options) end # returns a new Hash with string keys instead of symbol keys. - def stringify_hash_keys(hash) + def stringify_hash_keys hash Hash[hash.map { |k, v| [k.to_s, v] }] end - def client_options(options) + def client_options options # Keyfile options have higher priority over constructor defaults options["token_credential_uri"] ||= self.class::TOKEN_CREDENTIAL_URI options["audience"] ||= self.class::AUDIENCE @@ -179,10 +177,10 @@ module Google # client options for initializing signet client { token_credential_uri: options["token_credential_uri"], - audience: options["audience"], - scope: Array(options["scope"]), - issuer: options["client_email"], - signing_key: OpenSSL::PKey::RSA.new(options["private_key"]) } + audience: options["audience"], + scope: Array(options["scope"]), + issuer: options["client_email"], + signing_key: OpenSSL::PKey::RSA.new(options["private_key"]) } end end end diff --git a/lib/googleauth/credentials_loader.rb b/lib/googleauth/credentials_loader.rb index 9e1b744..421d072 100644 --- a/lib/googleauth/credentials_loader.rb +++ b/lib/googleauth/credentials_loader.rb @@ -75,11 +75,9 @@ module Google # # By default, it calls #new on the current class, but this behaviour can # be modified, allowing different instances to be created. - def make_creds(*args) + def make_creds *args creds = new(*args) - if creds.respond_to?(:configure_connection) && args.size == 1 - creds = creds.configure_connection(args[0]) - end + creds = creds.configure_connection args[0] if creds.respond_to?(:configure_connection) && args.size == 1 creds end @@ -95,16 +93,16 @@ module Google # The following keys are recognized: # * `:default_connection` The connection object to use. # * `:connection_builder` A `Proc` that returns a connection. - def from_env(scope = nil, options = {}) + def from_env scope = nil, options = {} options = interpret_options scope, options - if ENV.key?(ENV_VAR) + if ENV.key? ENV_VAR path = ENV[ENV_VAR] - raise "file #{path} does not exist" unless File.exist?(path) - File.open(path) do |f| - return make_creds(options.merge(json_key_io: f)) + raise "file #{path} does not exist" unless File.exist? path + File.open path do |f| + return make_creds options.merge(json_key_io: f) end elsif service_account_env_vars? || authorized_user_env_vars? - return make_creds(options) + return make_creds options end rescue StandardError => e raise "#{NOT_FOUND_ERROR}: #{e}" @@ -121,16 +119,16 @@ module Google # The following keys are recognized: # * `:default_connection` The connection object to use. # * `:connection_builder` A `Proc` that returns a connection. - def from_well_known_path(scope = nil, options = {}) + def from_well_known_path scope = nil, options = {} options = interpret_options scope, options home_var = OS.windows? ? "APPDATA" : "HOME" base = WELL_KNOWN_PATH root = ENV[home_var].nil? ? "" : ENV[home_var] - base = File.join(".config", base) unless OS.windows? - path = File.join(root, base) - return nil unless File.exist?(path) - File.open(path) do |f| - return make_creds(options.merge(json_key_io: f)) + base = File.join ".config", base unless OS.windows? + path = File.join root, base + return nil unless File.exist? path + File.open path do |f| + return make_creds options.merge(json_key_io: f) end rescue StandardError => e raise "#{WELL_KNOWN_ERROR}: #{e}" @@ -147,28 +145,29 @@ module Google # The following keys are recognized: # * `:default_connection` The connection object to use. # * `:connection_builder` A `Proc` that returns a connection. - def from_system_default_path(scope = nil, options = {}) + def from_system_default_path scope = nil, options = {} options = interpret_options scope, options if OS.windows? return nil unless ENV["ProgramData"] - prefix = File.join(ENV["ProgramData"], "Google/Auth") + prefix = File.join ENV["ProgramData"], "Google/Auth" else prefix = "/etc/google/auth/" end - path = File.join(prefix, CREDENTIALS_FILE_NAME) - return nil unless File.exist?(path) - File.open(path) do |f| - return make_creds(options.merge(json_key_io: f)) + path = File.join prefix, CREDENTIALS_FILE_NAME + return nil unless File.exist? path + File.open path do |f| + return make_creds options.merge(json_key_io: f) end rescue StandardError => e raise "#{SYSTEM_DEFAULT_ERROR}: #{e}" end + module_function + # Issues warning if cloud sdk client id is used - def warn_if_cloud_sdk_credentials(client_id) + def warn_if_cloud_sdk_credentials client_id warn CLOUD_SDK_CREDENTIALS_WARNING if client_id == CLOUD_SDK_CLIENT_ID end - module_function :warn_if_cloud_sdk_credentials # Finds project_id from gcloud CLI configuration def load_gcloud_project_id @@ -177,23 +176,19 @@ module Google gcloud_json = IO.popen("#{gcloud} #{GCLOUD_CONFIG_COMMAND}", &:read) config = MultiJson.load gcloud_json config["configuration"]["properties"]["core"]["project"] - rescue + rescue StandardError nil end - module_function :load_gcloud_project_id private - def interpret_options(scope, options) + def interpret_options scope, options if scope.is_a? Hash options = scope scope = nil end - if scope && !options[:scope] - options.merge(scope: scope) - else - options - end + return options.merge scope: scope if scope && !options[:scope] + options end def service_account_env_vars? @@ -201,8 +196,7 @@ module Google end def authorized_user_env_vars? - ([CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR] - - ENV.keys).empty? + ([CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR] - ENV.keys).empty? end end end diff --git a/lib/googleauth/default_credentials.rb b/lib/googleauth/default_credentials.rb index c14928b..f9e7d1a 100644 --- a/lib/googleauth/default_credentials.rb +++ b/lib/googleauth/default_credentials.rb @@ -45,17 +45,17 @@ module Google # override CredentialsLoader#make_creds to use the class determined by # loading the json. - def self.make_creds(options = {}) + def self.make_creds options = {} json_key_io = options[:json_key_io] if json_key_io - json_key, clz = determine_creds_class(json_key_io) + json_key, clz = determine_creds_class json_key_io warn_if_cloud_sdk_credentials json_key["client_id"] - io = StringIO.new(MultiJson.dump(json_key)) - clz.make_creds(options.merge(json_key_io: io)) + io = StringIO.new MultiJson.dump(json_key) + clz.make_creds options.merge(json_key_io: io) else warn_if_cloud_sdk_credentials ENV[CredentialsLoader::CLIENT_ID_VAR] clz = read_creds - clz.make_creds(options) + clz.make_creds options end end @@ -74,10 +74,10 @@ module Google end # Reads the input json and determines which creds class to use. - def self.determine_creds_class(json_key_io) + def self.determine_creds_class json_key_io json_key = MultiJson.load json_key_io.read key = "type" - raise "the json is missing the '#{key}' field" unless json_key.key?(key) + raise "the json is missing the '#{key}' field" unless json_key.key? key type = json_key[key] case type when "service_account" diff --git a/lib/googleauth/iam.rb b/lib/googleauth/iam.rb index 8abe983..606f357 100644 --- a/lib/googleauth/iam.rb +++ b/lib/googleauth/iam.rb @@ -44,7 +44,7 @@ module Google # # @param selector the IAM selector. # @param token the IAM token. - def initialize(selector, token) + def initialize selector, token raise TypeError unless selector.is_a? String raise TypeError unless token.is_a? String @selector = selector @@ -52,16 +52,16 @@ module Google end # Adds the credential fields to the hash. - def apply!(a_hash) + def apply! a_hash a_hash[SELECTOR_KEY] = @selector a_hash[TOKEN_KEY] = @token a_hash end # Returns a clone of a_hash updated with the authoriation header - def apply(a_hash) + def apply a_hash a_copy = a_hash.clone - apply!(a_copy) + apply! a_copy a_copy end diff --git a/lib/googleauth/json_key_reader.rb b/lib/googleauth/json_key_reader.rb index 79dbb14..4f5002f 100644 --- a/lib/googleauth/json_key_reader.rb +++ b/lib/googleauth/json_key_reader.rb @@ -34,10 +34,10 @@ module Google # JsonKeyReader contains the behaviour used to read private key and # client email fields from the service account module JsonKeyReader - def read_json_key(json_key_io) - json_key = MultiJson.load(json_key_io.read) - raise "missing client_email" unless json_key.key?("client_email") - raise "missing private_key" unless json_key.key?("private_key") + def read_json_key json_key_io + json_key = MultiJson.load json_key_io.read + raise "missing client_email" unless json_key.key? "client_email" + raise "missing private_key" unless json_key.key? "private_key" project_id = json_key["project_id"] [json_key["private_key"], json_key["client_email"], project_id] end diff --git a/lib/googleauth/scope_util.rb b/lib/googleauth/scope_util.rb index 0894226..c3f0305 100644 --- a/lib/googleauth/scope_util.rb +++ b/lib/googleauth/scope_util.rb @@ -36,22 +36,22 @@ module Google # Small utility for normalizing scopes into canonical form module ScopeUtil ALIASES = { - "email" => "https://www.googleapis.com/auth/userinfo.email", + "email" => "https://www.googleapis.com/auth/userinfo.email", "profile" => "https://www.googleapis.com/auth/userinfo.profile", - "openid" => "https://www.googleapis.com/auth/plus.me" + "openid" => "https://www.googleapis.com/auth/plus.me" }.freeze - def self.normalize(scope) - list = as_array(scope) + def self.normalize scope + list = as_array scope list.map { |item| ALIASES[item] || item } end - def self.as_array(scope) + def self.as_array scope case scope when Array scope when String - scope.split(" ") + scope.split " " else raise "Invalid scope value. Must be string or array" end diff --git a/lib/googleauth/service_account.rb b/lib/googleauth/service_account.rb index ffedea6..849b6ae 100644 --- a/lib/googleauth/service_account.rb +++ b/lib/googleauth/service_account.rb @@ -56,10 +56,10 @@ module Google # # @param json_key_io [IO] an IO from which the JSON key can be read # @param scope [string|array|nil] the scope(s) to access - def self.make_creds(options = {}) - json_key_io, scope = options.values_at(:json_key_io, :scope) + def self.make_creds options = {} + json_key_io, scope = options.values_at :json_key_io, :scope if json_key_io - private_key, client_email, project_id = read_json_key(json_key_io) + private_key, client_email, project_id = read_json_key json_key_io else private_key = unescape ENV[CredentialsLoader::PRIVATE_KEY_VAR] client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR] @@ -68,26 +68,26 @@ module Google project_id ||= CredentialsLoader.load_gcloud_project_id new(token_credential_uri: TOKEN_CRED_URI, - audience: TOKEN_CRED_URI, - scope: scope, - issuer: client_email, - signing_key: OpenSSL::PKey::RSA.new(private_key), - project_id: project_id) + audience: TOKEN_CRED_URI, + scope: scope, + issuer: client_email, + signing_key: OpenSSL::PKey::RSA.new(private_key), + project_id: project_id) .configure_connection(options) end # Handles certain escape sequences that sometimes appear in input. # Specifically, interprets the "\n" sequence for newline, and removes # enclosing quotes. - def self.unescape(str) + def self.unescape str str = str.gsub '\n', "\n" str = str[1..-2] if str.start_with?('"') && str.end_with?('"') str end - def initialize(options = {}) + def initialize options = {} @project_id = options[:project_id] - super(options) + super options end # Extends the base class. @@ -95,7 +95,7 @@ module Google # If scope(s) is not set, it creates a transient # ServiceAccountJwtHeaderCredentials instance and uses that to # authenticate instead. - def apply!(a_hash, opts = {}) + def apply! a_hash, opts = {} # Use the base implementation if scopes are set unless scope.nil? super @@ -105,13 +105,13 @@ module Google # Use the ServiceAccountJwtHeaderCredentials using the same cred values # if no scopes are set. cred_json = { - private_key: @signing_key.to_s, + private_key: @signing_key.to_s, client_email: @issuer } alt_clz = ServiceAccountJwtHeaderCredentials - key_io = StringIO.new(MultiJson.dump(cred_json)) - alt = alt_clz.make_creds(json_key_io: key_io) - alt.apply!(a_hash) + key_io = StringIO.new MultiJson.dump(cred_json) + alt = alt_clz.make_creds json_key_io: key_io + alt.apply! a_hash end end @@ -141,43 +141,43 @@ module Google # By default, it calls #new with 2 args, the second one being an # optional scope. Here's the constructor only has one param, so # we modify make_creds to reflect this. - def self.make_creds(*args) - new(json_key_io: args[0][:json_key_io]) + def self.make_creds *args + new json_key_io: args[0][:json_key_io] end # Initializes a ServiceAccountJwtHeaderCredentials. # # @param json_key_io [IO] an IO from which the JSON key can be read - def initialize(options = {}) + def initialize options = {} json_key_io = options[:json_key_io] if json_key_io @private_key, @issuer, @project_id = - self.class.read_json_key(json_key_io) + self.class.read_json_key json_key_io else @private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR] @issuer = ENV[CredentialsLoader::CLIENT_EMAIL_VAR] @project_id = ENV[CredentialsLoader::PROJECT_ID_VAR] end @project_id ||= CredentialsLoader.load_gcloud_project_id - @signing_key = OpenSSL::PKey::RSA.new(@private_key) + @signing_key = OpenSSL::PKey::RSA.new @private_key end # Construct a jwt token if the JWT_AUD_URI key is present in the input # hash. # # The jwt token is used as the value of a 'Bearer '. - def apply!(a_hash, opts = {}) - jwt_aud_uri = a_hash.delete(JWT_AUD_URI_KEY) + def apply! a_hash, opts = {} + jwt_aud_uri = a_hash.delete JWT_AUD_URI_KEY return a_hash if jwt_aud_uri.nil? - jwt_token = new_jwt_token(jwt_aud_uri, opts) + jwt_token = new_jwt_token jwt_aud_uri, opts a_hash[AUTH_METADATA_KEY] = "Bearer #{jwt_token}" a_hash end # Returns a clone of a_hash updated with the authoriation header - def apply(a_hash, opts = {}) + def apply a_hash, opts = {} a_copy = a_hash.clone - apply!(a_copy, opts) + apply! a_copy, opts a_copy end @@ -190,7 +190,7 @@ module Google protected # Creates a jwt uri token. - def new_jwt_token(jwt_aud_uri, options = {}) + def new_jwt_token jwt_aud_uri, options = {} now = Time.new skew = options[:skew] || 60 assertion = { @@ -200,7 +200,7 @@ module Google "exp" => (now + EXPIRY).to_i, "iat" => (now - skew).to_i } - JWT.encode(assertion, @signing_key, SIGNING_ALGORITHM) + JWT.encode assertion, @signing_key, SIGNING_ALGORITHM end end end diff --git a/lib/googleauth/signet.rb b/lib/googleauth/signet.rb index c8e5b36..cdb9256 100644 --- a/lib/googleauth/signet.rb +++ b/lib/googleauth/signet.rb @@ -38,24 +38,24 @@ module Signet # This reopens Client to add #apply and #apply! methods which update a # hash with the fetched authentication token. class Client - def configure_connection(options) + def configure_connection options @connection_info = options[:connection_builder] || options[:default_connection] self end # Updates a_hash updated with the authentication token - def apply!(a_hash, opts = {}) + def apply! a_hash, opts = {} # fetch the access token there is currently not one, or if the client # has expired - fetch_access_token!(opts) if access_token.nil? || expires_within?(60) + fetch_access_token! opts if access_token.nil? || expires_within?(60) a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}" end # Returns a clone of a_hash updated with the authentication token - def apply(a_hash, opts = {}) + def apply a_hash, opts = {} a_copy = a_hash.clone - apply!(a_copy, opts) + apply! a_copy, opts a_copy end @@ -65,18 +65,18 @@ module Signet lambda(&method(:apply)) end - def on_refresh(&block) + def on_refresh &block @refresh_listeners ||= [] @refresh_listeners << block end alias orig_fetch_access_token! fetch_access_token! - def fetch_access_token!(options = {}) + def fetch_access_token! options = {} unless options[:connection] connection = build_default_connection - options = options.merge(connection: connection) if connection + options = options.merge connection: connection if connection end - info = orig_fetch_access_token!(options) + info = orig_fetch_access_token! options notify_refresh_listeners info end @@ -84,7 +84,7 @@ module Signet def notify_refresh_listeners listeners = @refresh_listeners || [] listeners.each do |block| - block.call(self) + block.call self end end @@ -98,15 +98,13 @@ module Signet end end - def retry_with_error(max_retry_count = 5) + def retry_with_error max_retry_count = 5 retry_count = 0 begin yield - rescue => e - if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError) - raise e - end + rescue StandardError => e + raise e if e.is_a?(Signet::AuthorizationError) || e.is_a?(Signet::ParseError) if retry_count < max_retry_count retry_count += 1 @@ -114,7 +112,7 @@ module Signet retry else msg = "Unexpected error: #{e.inspect}" - raise(Signet::AuthorizationError, msg) + raise Signet::AuthorizationError, msg end end end diff --git a/lib/googleauth/stores/file_token_store.rb b/lib/googleauth/stores/file_token_store.rb index dae15e5..a2268e3 100644 --- a/lib/googleauth/stores/file_token_store.rb +++ b/lib/googleauth/stores/file_token_store.rb @@ -39,24 +39,24 @@ module Google # # @param [String, File] file # Path to storage file - def initialize(options = {}) + def initialize options = {} path = options[:file] - @store = YAML::Store.new(path) + @store = YAML::Store.new path end # (see Google::Auth::Stores::TokenStore#load) - def load(id) + def load id @store.transaction { @store[id] } end # (see Google::Auth::Stores::TokenStore#store) - def store(id, token) + def store id, token @store.transaction { @store[id] = token } end # (see Google::Auth::Stores::TokenStore#delete) - def delete(id) - @store.transaction { @store.delete(id) } + def delete id + @store.transaction { @store.delete id } end end end diff --git a/lib/googleauth/stores/redis_token_store.rb b/lib/googleauth/stores/redis_token_store.rb index 8d5ddcd..0a8aef2 100644 --- a/lib/googleauth/stores/redis_token_store.rb +++ b/lib/googleauth/stores/redis_token_store.rb @@ -48,34 +48,34 @@ module Google # @note If no redis instance is provided, a new one is created and # the options passed through. You may include any other keys accepted # by `Redis.new` - def initialize(options = {}) - redis = options.delete(:redis) - prefix = options.delete(:prefix) + def initialize options = {} + redis = options.delete :redis + prefix = options.delete :prefix @redis = case redis when Redis redis else - Redis.new(options) + Redis.new options end @prefix = prefix || DEFAULT_KEY_PREFIX end # (see Google::Auth::Stores::TokenStore#load) - def load(id) - key = key_for(id) - @redis.get(key) + def load id + key = key_for id + @redis.get key end # (see Google::Auth::Stores::TokenStore#store) - def store(id, token) - key = key_for(id) - @redis.set(key, token) + def store id, token + key = key_for id + @redis.set key, token end # (see Google::Auth::Stores::TokenStore#delete) - def delete(id) - key = key_for(id) - @redis.del(key) + def delete id + key = key_for id + @redis.del key end private @@ -86,7 +86,7 @@ module Google # ID of the token # @return [String] # Redis key - def key_for(id) + def key_for id @prefix + id end end diff --git a/lib/googleauth/token_store.rb b/lib/googleauth/token_store.rb index 5ed0887..eb82458 100644 --- a/lib/googleauth/token_store.rb +++ b/lib/googleauth/token_store.rb @@ -43,7 +43,7 @@ module Google # ID of token data to load. # @return [String] # The loaded token data. - def load(_id) + def load _id raise "Not implemented" end @@ -53,7 +53,7 @@ module Google # ID of token data to store. # @param [String] token # The token data to store. - def store(_id, _token) + def store _id, _token raise "Not implemented" end @@ -61,7 +61,7 @@ module Google # # @param [String] id # ID of the token data to delete - def delete(_id) + def delete _id raise "Not implemented" end end diff --git a/lib/googleauth/user_authorizer.rb b/lib/googleauth/user_authorizer.rb index 9c9fbc0..59f4647 100644 --- a/lib/googleauth/user_authorizer.rb +++ b/lib/googleauth/user_authorizer.rb @@ -72,7 +72,7 @@ module Google # @param [String] callback_uri # URL (either absolute or relative) of the auth callback. # Defaults to '/oauth2callback' - def initialize(client_id, scope, token_store, callback_uri = nil) + def initialize client_id, scope, token_store, callback_uri = nil raise NIL_CLIENT_ID_ERROR if client_id.nil? raise NIL_SCOPE_ERROR if scope.nil? @@ -97,20 +97,20 @@ module Google # nil. # @return [String] # Authorization url - def get_authorization_url(options = {}) + def get_authorization_url options = {} scope = options[:scope] || @scope credentials = UserRefreshCredentials.new( - client_id: @client_id.id, + client_id: @client_id.id, client_secret: @client_id.secret, - scope: scope + scope: scope ) - redirect_uri = redirect_uri_for(options[:base_url]) - url = credentials.authorization_uri(access_type: "offline", - redirect_uri: redirect_uri, - approval_prompt: "force", - state: options[:state], + redirect_uri = redirect_uri_for options[:base_url] + url = credentials.authorization_uri(access_type: "offline", + redirect_uri: redirect_uri, + approval_prompt: "force", + state: options[:state], include_granted_scopes: true, - login_hint: options[:login_hint]) + login_hint: options[:login_hint]) url.to_s end @@ -123,28 +123,26 @@ module Google # the requested scopes # @return [Google::Auth::UserRefreshCredentials] # Stored credentials, nil if none present - def get_credentials(user_id, scope = nil) - saved_token = stored_token(user_id) + def get_credentials user_id, scope = nil + saved_token = stored_token user_id return nil if saved_token.nil? - data = MultiJson.load(saved_token) + data = MultiJson.load saved_token if data.fetch("client_id", @client_id.id) != @client_id.id - raise sprintf(MISMATCHED_CLIENT_ID_ERROR, - data["client_id"], @client_id.id) + raise format(MISMATCHED_CLIENT_ID_ERROR, + data["client_id"], @client_id.id) end credentials = UserRefreshCredentials.new( - client_id: @client_id.id, + client_id: @client_id.id, client_secret: @client_id.secret, - scope: data["scope"] || @scope, - access_token: data["access_token"], + scope: data["scope"] || @scope, + access_token: data["access_token"], refresh_token: data["refresh_token"], - expires_at: data.fetch("expiration_time_millis", 0) / 1000 + expires_at: data.fetch("expiration_time_millis", 0) / 1000 ) scope ||= @scope - if credentials.includes_scope?(scope) - return monitor_credentials(user_id, credentials) - end + return monitor_credentials user_id, credentials if credentials.includes_scope? scope nil end @@ -163,20 +161,20 @@ module Google # callback uri is a relative. # @return [Google::Auth::UserRefreshCredentials] # Credentials if exchange is successful - def get_credentials_from_code(options = {}) + def get_credentials_from_code options = {} user_id = options[:user_id] code = options[:code] scope = options[:scope] || @scope base_url = options[:base_url] credentials = UserRefreshCredentials.new( - client_id: @client_id.id, + client_id: @client_id.id, client_secret: @client_id.secret, - redirect_uri: redirect_uri_for(base_url), - scope: scope + redirect_uri: redirect_uri_for(base_url), + scope: scope ) credentials.code = code credentials.fetch_access_token!({}) - monitor_credentials(user_id, credentials) + monitor_credentials user_id, credentials end # Exchanges an authorization code returned in the oauth callback. @@ -196,9 +194,9 @@ module Google # callback uri is a relative. # @return [Google::Auth::UserRefreshCredentials] # Credentials if exchange is successful - def get_and_store_credentials_from_code(options = {}) - credentials = get_credentials_from_code(options) - store_credentials(options[:user_id], credentials) + def get_and_store_credentials_from_code options = {} + credentials = get_credentials_from_code options + store_credentials options[:user_id], credentials end # Revokes a user's credentials. This both revokes the actual @@ -206,11 +204,11 @@ module Google # # @param [String] user_id # Unique ID of the user for loading/storing credentials. - def revoke_authorization(user_id) - credentials = get_credentials(user_id) + def revoke_authorization user_id + credentials = get_credentials user_id if credentials begin - @token_store.delete(user_id) + @token_store.delete user_id ensure credentials.revoke! end @@ -226,15 +224,15 @@ module Google # Unique ID of the user for loading/storing credentials. # @param [Google::Auth::UserRefreshCredentials] credentials # Credentials to store. - def store_credentials(user_id, credentials) + def store_credentials user_id, credentials json = MultiJson.dump( - client_id: credentials.client_id, - access_token: credentials.access_token, - refresh_token: credentials.refresh_token, - scope: credentials.scope, + client_id: credentials.client_id, + access_token: credentials.access_token, + refresh_token: credentials.refresh_token, + scope: credentials.scope, expiration_time_millis: credentials.expires_at.to_i * 1000 ) - @token_store.store(user_id, json) + @token_store.store user_id, json credentials end @@ -245,11 +243,11 @@ module Google # @param [String] user_id # Unique ID of the user for loading/storing credentials. # @return [String] The saved token from @token_store - def stored_token(user_id) + def stored_token user_id raise NIL_USER_ID_ERROR if user_id.nil? raise NIL_TOKEN_STORE_ERROR if @token_store.nil? - @token_store.load(user_id) + @token_store.load user_id end # Begin watching a credential for refreshes so the access token can be @@ -259,9 +257,9 @@ module Google # Unique ID of the user for loading/storing credentials. # @param [Google::Auth::UserRefreshCredentials] credentials # Credentials to store. - def monitor_credentials(user_id, credentials) + def monitor_credentials user_id, credentials credentials.on_refresh do |cred| - store_credentials(user_id, cred) + store_credentials user_id, cred end credentials end @@ -272,11 +270,9 @@ module Google # Absolute URL to resolve the callback against if necessary. # @return [String] # Redirect URI - def redirect_uri_for(base_url) + def redirect_uri_for base_url return @callback_uri unless URI(@callback_uri).scheme.nil? - if base_url.nil? || URI(base_url).scheme.nil? - raise sprintf(MISSING_ABSOLUTE_URL_ERROR, @callback_uri) - end + raise format(MISSING_ABSOLUTE_URL_ERROR, @callback_uri) if base_url.nil? || URI(base_url).scheme.nil? URI.join(base_url, @callback_uri).to_s end end diff --git a/lib/googleauth/user_refresh.rb b/lib/googleauth/user_refresh.rb index bac4a4b..0fb9abc 100644 --- a/lib/googleauth/user_refresh.rb +++ b/lib/googleauth/user_refresh.rb @@ -56,9 +56,9 @@ module Google # # @param json_key_io [IO] an IO from which the JSON key can be read # @param scope [string|array|nil] the scope(s) to access - def self.make_creds(options = {}) - json_key_io, scope = options.values_at(:json_key_io, :scope) - user_creds = read_json_key(json_key_io) if json_key_io + def self.make_creds options = {} + json_key_io, scope = options.values_at :json_key_io, :scope + user_creds = read_json_key json_key_io if json_key_io user_creds ||= { "client_id" => ENV[CredentialsLoader::CLIENT_ID_VAR], "client_secret" => ENV[CredentialsLoader::CLIENT_SECRET_VAR], @@ -67,36 +67,36 @@ module Google } new(token_credential_uri: TOKEN_CRED_URI, - client_id: user_creds["client_id"], - client_secret: user_creds["client_secret"], - refresh_token: user_creds["refresh_token"], - project_id: user_creds["project_id"], - scope: scope) + client_id: user_creds["client_id"], + client_secret: user_creds["client_secret"], + refresh_token: user_creds["refresh_token"], + project_id: user_creds["project_id"], + scope: scope) .configure_connection(options) end # Reads the client_id, client_secret and refresh_token fields from the # JSON key. - def self.read_json_key(json_key_io) - json_key = MultiJson.load(json_key_io.read) - wanted = %w(client_id client_secret refresh_token) + def self.read_json_key json_key_io + json_key = MultiJson.load json_key_io.read + wanted = %w[client_id client_secret refresh_token] wanted.each do |key| - raise "the json is missing the #{key} field" unless json_key.key?(key) + raise "the json is missing the #{key} field" unless json_key.key? key end json_key end - def initialize(options = {}) + def initialize options = {} options ||= {} options[:token_credential_uri] ||= TOKEN_CRED_URI options[:authorization_uri] ||= AUTHORIZATION_URI @project_id = options[:project_id] @project_id ||= CredentialsLoader.load_gcloud_project_id - super(options) + super options end # Revokes the credential - def revoke!(options = {}) + def revoke! options = {} c = options[:connection] || Faraday.default_connection retry_with_error do @@ -119,7 +119,7 @@ module Google # Scope to verify # @return [Boolean] # True if scope is granted - def includes_scope?(required_scope) + def includes_scope? required_scope missing_scope = Google::Auth::ScopeUtil.normalize(required_scope) - Google::Auth::ScopeUtil.normalize(scope) missing_scope.empty? diff --git a/lib/googleauth/web_user_authorizer.rb b/lib/googleauth/web_user_authorizer.rb index af23c87..be6c9d8 100644 --- a/lib/googleauth/web_user_authorizer.rb +++ b/lib/googleauth/web_user_authorizer.rb @@ -97,9 +97,9 @@ module Google # # @param [Rack::Request] request # Current request - def self.handle_auth_callback_deferred(request) - callback_state, redirect_uri = extract_callback_state(request) - request.session[CALLBACK_STATE_KEY] = MultiJson.dump(callback_state) + def self.handle_auth_callback_deferred request + callback_state, redirect_uri = extract_callback_state request + request.session[CALLBACK_STATE_KEY] = MultiJson.dump callback_state redirect_uri end @@ -114,8 +114,8 @@ module Google # @param [String] callback_uri # URL (either absolute or relative) of the auth callback. Defaults # to '/oauth2callback' - def initialize(client_id, scope, token_store, callback_uri = nil) - super(client_id, scope, token_store, callback_uri) + def initialize client_id, scope, token_store, callback_uri = nil + super client_id, scope, token_store, callback_uri end # Handle the result of the oauth callback. Exchanges the authorization @@ -127,15 +127,15 @@ module Google # Current request # @return (Google::Auth::UserRefreshCredentials, String) # credentials & next URL to redirect to - def handle_auth_callback(user_id, request) + def handle_auth_callback user_id, request callback_state, redirect_uri = WebUserAuthorizer.extract_callback_state( request ) - WebUserAuthorizer.validate_callback_state(callback_state, request) + WebUserAuthorizer.validate_callback_state callback_state, request credentials = get_and_store_credentials_from_code( - user_id: user_id, - code: callback_state[AUTH_CODE_KEY], - scope: callback_state[SCOPE_KEY], + user_id: user_id, + code: callback_state[AUTH_CODE_KEY], + scope: callback_state[SCOPE_KEY], base_url: request.url ) [credentials, redirect_uri] @@ -156,7 +156,7 @@ module Google # not nil. # @return [String] # Authorization url - def get_authorization_url(options = {}) + def get_authorization_url options = {} options = options.dup request = options[:request] raise NIL_REQUEST_ERROR if request.nil? @@ -165,11 +165,11 @@ module Google redirect_to = options[:redirect_to] || request.url request.session[XSRF_KEY] = SecureRandom.base64 options[:state] = MultiJson.dump( - SESSION_ID_KEY => request.session[XSRF_KEY], + SESSION_ID_KEY => request.session[XSRF_KEY], CURRENT_URI_KEY => redirect_to ) options[:base_url] = request.url - super(options) + super options end # Fetch stored credentials for the user. @@ -186,32 +186,32 @@ module Google # @raise [Signet::AuthorizationError] # May raise an error if an authorization code is present in the session # and exchange of the code fails - def get_credentials(user_id, request, scope = nil) - if request.session.key?(CALLBACK_STATE_KEY) + def get_credentials user_id, request, scope = nil + if request.session.key? CALLBACK_STATE_KEY # Note - in theory, no need to check required scope as this is # expected to be called immediately after a return from authorization - state_json = request.session.delete(CALLBACK_STATE_KEY) - callback_state = MultiJson.load(state_json) - WebUserAuthorizer.validate_callback_state(callback_state, request) + state_json = request.session.delete CALLBACK_STATE_KEY + callback_state = MultiJson.load state_json + WebUserAuthorizer.validate_callback_state callback_state, request get_and_store_credentials_from_code( - user_id: user_id, - code: callback_state[AUTH_CODE_KEY], - scope: callback_state[SCOPE_KEY], + user_id: user_id, + code: callback_state[AUTH_CODE_KEY], + scope: callback_state[SCOPE_KEY], base_url: request.url ) else - super(user_id, scope) + super user_id, scope end end - def self.extract_callback_state(request) + def self.extract_callback_state request state = MultiJson.load(request[STATE_PARAM] || "{}") redirect_uri = state[CURRENT_URI_KEY] callback_state = { - AUTH_CODE_KEY => request[AUTH_CODE_KEY], + AUTH_CODE_KEY => request[AUTH_CODE_KEY], ERROR_CODE_KEY => request[ERROR_CODE_KEY], SESSION_ID_KEY => state[SESSION_ID_KEY], - SCOPE_KEY => request[SCOPE_KEY] + SCOPE_KEY => request[SCOPE_KEY] } [callback_state, redirect_uri] end @@ -226,12 +226,11 @@ module Google # Error message if failed # @param [Rack::Request] request # Current request - def self.validate_callback_state(state, request) - if state[AUTH_CODE_KEY].nil? - raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR - elsif state[ERROR_CODE_KEY] + def self.validate_callback_state state, request + raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR if state[AUTH_CODE_KEY].nil? + if state[ERROR_CODE_KEY] raise Signet::AuthorizationError, - sprintf(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY]) + format(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY]) elsif request.session[XSRF_KEY] != state[SESSION_ID_KEY] raise Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR end @@ -275,9 +274,9 @@ module Google # Rack environment # @return [Array] # HTTP response - def self.call(env) - request = Rack::Request.new(env) - return_url = WebUserAuthorizer.handle_auth_callback_deferred(request) + def self.call env + request = Rack::Request.new env + return_url = WebUserAuthorizer.handle_auth_callback_deferred request if return_url [REDIR_STATUS, { LOCATION_HEADER => return_url }, []] else @@ -285,8 +284,8 @@ module Google end end - def call(env) - self.class.call(env) + def call env + self.class.call env end end end diff --git a/spec/googleauth/apply_auth_examples.rb b/spec/googleauth/apply_auth_examples.rb index d38f9ad..ee9ac72 100644 --- a/spec/googleauth/apply_auth_examples.rb +++ b/spec/googleauth/apply_auth_examples.rb @@ -27,14 +27,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'faraday' -require 'spec_helper' +require "faraday" +require "spec_helper" -shared_examples 'apply/apply! are OK' do +shared_examples "apply/apply! are OK" do let(:auth_key) { :authorization } # tests that use these examples need to define @@ -43,103 +43,103 @@ shared_examples 'apply/apply! are OK' do # # @make_auth_stubs, which should stub out the expected http behaviour of the # auth client - describe '#fetch_access_token' do - let(:token) { '1/abcdef1234567890' } - let(:stub) do + describe "#fetch_access_token" do + let(:token) { "1/abcdef1234567890" } + let :stub do make_auth_stubs access_token: token end - it 'should set access_token to the fetched value' do + it "should set access_token to the fetched value" do stub @client.fetch_access_token! expect(@client.access_token).to eq(token) expect(stub).to have_been_requested end - it 'should notify refresh listeners after updating' do + it "should notify refresh listeners after updating" do stub expect do |b| @client.on_refresh(&b) @client.fetch_access_token! end.to yield_with_args(have_attributes( - access_token: '1/abcdef1234567890' - )) + access_token: "1/abcdef1234567890" + )) expect(stub).to have_been_requested end end - describe '#apply!' do - it 'should update the target hash with fetched access token' do - token = '1/abcdef1234567890' + describe "#apply!" do + it "should update the target hash with fetched access token" do + token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token - md = { foo: 'bar' } - @client.apply!(md) - want = { :foo => 'bar', auth_key => "Bearer #{token}" } + md = { foo: "bar" } + @client.apply! md + want = { :foo => "bar", auth_key => "Bearer #{token}" } expect(md).to eq(want) expect(stub).to have_been_requested end end - describe 'updater_proc' do - it 'should provide a proc that updates a hash with the access token' do - token = '1/abcdef1234567890' + describe "updater_proc" do + it "should provide a proc that updates a hash with the access token" do + token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token - md = { foo: 'bar' } + md = { foo: "bar" } the_proc = @client.updater_proc - got = the_proc.call(md) - want = { :foo => 'bar', auth_key => "Bearer #{token}" } + got = the_proc.call md + want = { :foo => "bar", auth_key => "Bearer #{token}" } expect(got).to eq(want) expect(stub).to have_been_requested end end - describe '#apply' do - it 'should not update the original hash with the access token' do - token = '1/abcdef1234567890' + describe "#apply" do + it "should not update the original hash with the access token" do + token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token - md = { foo: 'bar' } - @client.apply(md) - want = { foo: 'bar' } + md = { foo: "bar" } + @client.apply md + want = { foo: "bar" } expect(md).to eq(want) expect(stub).to have_been_requested end - it 'should add the token to the returned hash' do - token = '1/abcdef1234567890' + it "should add the token to the returned hash" do + token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token - md = { foo: 'bar' } - got = @client.apply(md) - want = { :foo => 'bar', auth_key => "Bearer #{token}" } + md = { foo: "bar" } + got = @client.apply md + want = { :foo => "bar", auth_key => "Bearer #{token}" } expect(got).to eq(want) expect(stub).to have_been_requested end - it 'should not fetch a new token if the current is not expired' do - token = '1/abcdef1234567890' + it "should not fetch a new token if the current is not expired" do + token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token n = 5 # arbitrary n.times do |_t| - md = { foo: 'bar' } - got = @client.apply(md) - want = { :foo => 'bar', auth_key => "Bearer #{token}" } + md = { foo: "bar" } + got = @client.apply md + want = { :foo => "bar", auth_key => "Bearer #{token}" } expect(got).to eq(want) end expect(stub).to have_been_requested end - it 'should fetch a new token if the current one is expired' do - token1 = '1/abcdef1234567890' - token2 = '2/abcdef1234567891' + it "should fetch a new token if the current one is expired" do + token1 = "1/abcdef1234567890" + token2 = "2/abcdef1234567891" [token1, token2].each do |t| make_auth_stubs access_token: t - md = { foo: 'bar' } - got = @client.apply(md) - want = { :foo => 'bar', auth_key => "Bearer #{t}" } + md = { foo: "bar" } + got = @client.apply md + want = { :foo => "bar", auth_key => "Bearer #{t}" } expect(got).to eq(want) @client.expires_at -= 3601 # default is to expire in 1hr end diff --git a/spec/googleauth/client_id_spec.rb b/spec/googleauth/client_id_spec.rb index 693d4b4..bc6520e 100644 --- a/spec/googleauth/client_id_spec.rb +++ b/spec/googleauth/client_id_spec.rb @@ -27,131 +27,131 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'spec_helper' -require 'fakefs/safe' -require 'googleauth' +require "spec_helper" +require "fakefs/safe" +require "googleauth" describe Google::Auth::ClientId do - shared_examples 'it has a valid config' do - it 'should include a valid id' do - expect(client_id.id).to eql 'abc@example.com' + shared_examples "it has a valid config" do + it "should include a valid id" do + expect(client_id.id).to eql "abc@example.com" end - it 'should include a valid secret' do - expect(client_id.secret).to eql 'notasecret' + it "should include a valid secret" do + expect(client_id.secret).to eql "notasecret" end end - shared_examples 'it can successfully load client_id' do - context 'loaded from hash' do + shared_examples "it can successfully load client_id" do + context "loaded from hash" do let(:client_id) { Google::Auth::ClientId.from_hash config } - it_behaves_like 'it has a valid config' + it_behaves_like "it has a valid config" end - context 'loaded from file' do - file_path = '/client_secrets.json' + context "loaded from file" do + file_path = "/client_secrets.json" - let(:client_id) do + let :client_id do FakeFS do - content = MultiJson.dump(config) - File.write(file_path, content) - Google::Auth::ClientId.from_file(file_path) + content = MultiJson.dump config + File.write file_path, content + Google::Auth::ClientId.from_file file_path end end - it_behaves_like 'it has a valid config' + it_behaves_like "it has a valid config" end end - describe 'with web config' do - let(:config) do + describe "with web config" do + let :config do { - 'web' => { - 'client_id' => 'abc@example.com', - 'client_secret' => 'notasecret' + "web" => { + "client_id" => "abc@example.com", + "client_secret" => "notasecret" } } end - it_behaves_like 'it can successfully load client_id' + it_behaves_like "it can successfully load client_id" end - describe 'with installed app config' do - let(:config) do + describe "with installed app config" do + let :config do { - 'installed' => { - 'client_id' => 'abc@example.com', - 'client_secret' => 'notasecret' + "installed" => { + "client_id" => "abc@example.com", + "client_secret" => "notasecret" } } end - it_behaves_like 'it can successfully load client_id' + it_behaves_like "it can successfully load client_id" end - context 'with missing top level property' do - let(:config) do + context "with missing top level property" do + let :config do { - 'notvalid' => { - 'client_id' => 'abc@example.com', - 'client_secret' => 'notasecret' + "notvalid" => { + "client_id" => "abc@example.com", + "client_secret" => "notasecret" } } end - it 'should raise error' do + it "should raise error" do expect { Google::Auth::ClientId.from_hash config }.to raise_error( /Expected top level property/ ) end end - context 'with missing client id' do - let(:config) do + context "with missing client id" do + let :config do { - 'web' => { - 'client_secret' => 'notasecret' + "web" => { + "client_secret" => "notasecret" } } end - it 'should raise error' do + it "should raise error" do expect { Google::Auth::ClientId.from_hash config }.to raise_error( /Client id can not be nil/ ) end end - context 'with missing client secret' do - let(:config) do + context "with missing client secret" do + let :config do { - 'web' => { - 'client_id' => 'abc@example.com' + "web" => { + "client_id" => "abc@example.com" } } end - it 'should raise error' do + it "should raise error" do expect { Google::Auth::ClientId.from_hash config }.to raise_error( /Client secret can not be nil/ ) end end - context 'with cloud sdk credentials' do - let(:config) do + context "with cloud sdk credentials" do + let :config do { - 'web' => { - 'client_id' => Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID, - 'client_secret' => 'notasecret' + "web" => { + "client_id" => Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID, + "client_secret" => "notasecret" } } end - it 'should raise warning' do + it "should raise warning" do expect { Google::Auth::ClientId.from_hash config }.to output( Google::Auth::CredentialsLoader::CLOUD_SDK_CREDENTIALS_WARNING + "\n" ).to_stderr diff --git a/spec/googleauth/compute_engine_spec.rb b/spec/googleauth/compute_engine_spec.rb index f12d0ef..6429405 100644 --- a/spec/googleauth/compute_engine_spec.rb +++ b/spec/googleauth/compute_engine_spec.rb @@ -27,65 +27,65 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'apply_auth_examples' -require 'faraday' -require 'googleauth/compute_engine' -require 'spec_helper' +require "apply_auth_examples" +require "faraday" +require "googleauth/compute_engine" +require "spec_helper" describe Google::Auth::GCECredentials do - MD_URI = 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token'.freeze + MD_URI = "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token".freeze GCECredentials = Google::Auth::GCECredentials - before(:example) do + before :example do @client = GCECredentials.new end - def make_auth_stubs(opts = {}) - access_token = opts[:access_token] || '' - body = MultiJson.dump('access_token' => access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) + def make_auth_stubs opts = {} + access_token = opts[:access_token] || "" + body = MultiJson.dump("access_token" => access_token, + "token_type" => "Bearer", + "expires_in" => 3600) stub_request(:get, MD_URI) - .with(headers: { 'Metadata-Flavor' => 'Google' }) - .to_return(body: body, - status: 200, - headers: { 'Content-Type' => 'application/json' }) + .with(headers: { "Metadata-Flavor" => "Google" }) + .to_return(body: body, + status: 200, + headers: { "Content-Type" => "application/json" }) end - it_behaves_like 'apply/apply! are OK' + it_behaves_like "apply/apply! are OK" - context 'metadata is unavailable' do - describe '#fetch_access_token' do - it 'should fail if the metadata request returns a 404' do + context "metadata is unavailable" do + describe "#fetch_access_token" do + it "should fail if the metadata request returns a 404" do stub = stub_request(:get, MD_URI) - .to_return(status: 404, - headers: { 'Metadata-Flavor' => 'Google' }) + .to_return(status: 404, + headers: { "Metadata-Flavor" => "Google" }) expect { @client.fetch_access_token! } .to raise_error Signet::AuthorizationError expect(stub).to have_been_requested end - it 'should fail if the metadata request returns an unexpected code' do + it "should fail if the metadata request returns an unexpected code" do stub = stub_request(:get, MD_URI) - .to_return(status: 503, - headers: { 'Metadata-Flavor' => 'Google' }) + .to_return(status: 503, + headers: { "Metadata-Flavor" => "Google" }) expect { @client.fetch_access_token! } .to raise_error Signet::AuthorizationError expect(stub).to have_been_requested end - it 'should fail with Signet::AuthorizationError if request times out' do + it "should fail with Signet::AuthorizationError if request times out" do allow_any_instance_of(Faraday::Connection).to receive(:get) .and_raise(Faraday::TimeoutError) expect { @client.fetch_access_token! } .to raise_error Signet::AuthorizationError end - it 'should fail with Signet::AuthorizationError if request fails' do + it "should fail with Signet::AuthorizationError if request fails" do allow_any_instance_of(Faraday::Connection).to receive(:get) .and_raise(Faraday::ConnectionFailed, nil) expect { @client.fetch_access_token! } @@ -94,27 +94,27 @@ describe Google::Auth::GCECredentials do end end - describe '#on_gce?' do - it 'should be true when Metadata-Flavor is Google' do - stub = stub_request(:get, 'http://169.254.169.254') - .to_return(status: 200, - headers: { 'Metadata-Flavor' => 'Google' }) + describe "#on_gce?" do + it "should be true when Metadata-Flavor is Google" do + stub = stub_request(:get, "http://169.254.169.254") + .to_return(status: 200, + headers: { "Metadata-Flavor" => "Google" }) expect(GCECredentials.on_gce?({}, true)).to eq(true) expect(stub).to have_been_requested end - it 'should be false when Metadata-Flavor is not Google' do - stub = stub_request(:get, 'http://169.254.169.254') - .to_return(status: 200, - headers: { 'Metadata-Flavor' => 'NotGoogle' }) + it "should be false when Metadata-Flavor is not Google" do + stub = stub_request(:get, "http://169.254.169.254") + .to_return(status: 200, + headers: { "Metadata-Flavor" => "NotGoogle" }) expect(GCECredentials.on_gce?({}, true)).to eq(false) expect(stub).to have_been_requested end - it 'should be false if the response is not 200' do - stub = stub_request(:get, 'http://169.254.169.254') - .to_return(status: 404, - headers: { 'Metadata-Flavor' => 'NotGoogle' }) + it "should be false if the response is not 200" do + stub = stub_request(:get, "http://169.254.169.254") + .to_return(status: 404, + headers: { "Metadata-Flavor" => "NotGoogle" }) expect(GCECredentials.on_gce?({}, true)).to eq(false) expect(stub).to have_been_requested end diff --git a/spec/googleauth/credentials_spec.rb b/spec/googleauth/credentials_spec.rb index 24191b3..df4163d 100644 --- a/spec/googleauth/credentials_spec.rb +++ b/spec/googleauth/credentials_spec.rb @@ -27,34 +27,34 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require 'googleauth' +require "googleauth" # This test is testing the private class Google::Auth::Credentials. We want to # make sure that the passed in scope propogates to the Signet object. This means # testing the private API, which is generally frowned on. describe Google::Auth::Credentials, :private do - let(:default_keyfile_hash) do + let :default_keyfile_hash do { - 'private_key_id' => 'testabc1234567890xyz', - 'private_key' => "-----BEGIN RSA PRIVATE KEY-----\nMIIBOwIBAAJBAOyi0Hy1l4Ym2m2o71Q0TF4O9E81isZEsX0bb+Bqz1SXEaSxLiXM\nUZE8wu0eEXivXuZg6QVCW/5l+f2+9UPrdNUCAwEAAQJAJkqubA/Chj3RSL92guy3\nktzeodarLyw8gF8pOmpuRGSiEo/OLTeRUMKKD1/kX4f9sxf3qDhB4e7dulXR1co/\nIQIhAPx8kMW4XTTL6lJYd2K5GrH8uBMp8qL5ya3/XHrBgw3dAiEA7+3Iw3ULTn2I\n1J34WlJ2D5fbzMzB4FAHUNEV7Ys3f1kCIQDtUahCMChrl7+H5t9QS+xrn77lRGhs\nB50pjvy95WXpgQIhAI2joW6JzTfz8fAapb+kiJ/h9Vcs1ZN3iyoRlNFb61JZAiA8\nNy5NyNrMVwtB/lfJf1dAK/p/Bwd8LZLtgM6PapRfgw==\n-----END RSA PRIVATE KEY-----\n", - 'client_email' => 'credz-testabc1234567890xyz@developer.gserviceaccount.com', - 'client_id' => 'credz-testabc1234567890xyz.apps.googleusercontent.com', - 'type' => 'service_account', - 'project_id' => 'a_project_id' + "private_key_id" => "testabc1234567890xyz", + "private_key" => "-----BEGIN RSA PRIVATE KEY-----\nMIIBOwIBAAJBAOyi0Hy1l4Ym2m2o71Q0TF4O9E81isZEsX0bb+Bqz1SXEaSxLiXM\nUZE8wu0eEXivXuZg6QVCW/5l+f2+9UPrdNUCAwEAAQJAJkqubA/Chj3RSL92guy3\nktzeodarLyw8gF8pOmpuRGSiEo/OLTeRUMKKD1/kX4f9sxf3qDhB4e7dulXR1co/\nIQIhAPx8kMW4XTTL6lJYd2K5GrH8uBMp8qL5ya3/XHrBgw3dAiEA7+3Iw3ULTn2I\n1J34WlJ2D5fbzMzB4FAHUNEV7Ys3f1kCIQDtUahCMChrl7+H5t9QS+xrn77lRGhs\nB50pjvy95WXpgQIhAI2joW6JzTfz8fAapb+kiJ/h9Vcs1ZN3iyoRlNFb61JZAiA8\nNy5NyNrMVwtB/lfJf1dAK/p/Bwd8LZLtgM6PapRfgw==\n-----END RSA PRIVATE KEY-----\n", + "client_email" => "credz-testabc1234567890xyz@developer.gserviceaccount.com", + "client_id" => "credz-testabc1234567890xyz.apps.googleusercontent.com", + "type" => "service_account", + "project_id" => "a_project_id" } end - it 'uses a default scope' do - mocked_signet = double('Signet::OAuth2::Client') + it "uses a default scope" do + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") expect(options[:scope]).to eq([]) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -63,49 +63,49 @@ describe Google::Auth::Credentials, :private do Google::Auth::Credentials.new default_keyfile_hash end - it 'uses a custom scope' do - mocked_signet = double('Signet::OAuth2::Client') + it "uses a custom scope" do + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet end - Google::Auth::Credentials.new default_keyfile_hash, scope: 'http://example.com/scope' + Google::Auth::Credentials.new default_keyfile_hash, scope: "http://example.com/scope" end - it 'can be subclassed to pass in other env paths' do - TEST_PATH_ENV_VAR = 'TEST_PATH'.freeze - TEST_PATH_ENV_VAL = '/unknown/path/to/file.txt'.freeze - TEST_JSON_ENV_VAR = 'TEST_JSON_VARS'.freeze + it "can be subclassed to pass in other env paths" do + TEST_PATH_ENV_VAR = "TEST_PATH".freeze + TEST_PATH_ENV_VAL = "/unknown/path/to/file.txt".freeze + TEST_JSON_ENV_VAR = "TEST_JSON_VARS".freeze ENV[TEST_PATH_ENV_VAR] = TEST_PATH_ENV_VAL - ENV[TEST_JSON_ENV_VAR] = JSON.generate(default_keyfile_hash) + ENV[TEST_JSON_ENV_VAR] = JSON.generate default_keyfile_hash class TestCredentials < Google::Auth::Credentials - SCOPE = 'http://example.com/scope'.freeze + SCOPE = "http://example.com/scope".freeze PATH_ENV_VARS = [TEST_PATH_ENV_VAR].freeze JSON_ENV_VARS = [TEST_JSON_ENV_VAR].freeze end allow(::File).to receive(:file?).with(TEST_PATH_ENV_VAL) { false } - mocked_signet = double('Signet::OAuth2::Client') + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -114,32 +114,32 @@ describe Google::Auth::Credentials, :private do creds = TestCredentials.default expect(creds).to be_a_kind_of(TestCredentials) expect(creds.client).to eq(mocked_signet) - expect(creds.project_id).to eq(default_keyfile_hash['project_id']) + expect(creds.project_id).to eq(default_keyfile_hash["project_id"]) end - it 'subclasses can use PATH_ENV_VARS to get keyfile path' do + it "subclasses can use PATH_ENV_VARS to get keyfile path" do class TestCredentials < Google::Auth::Credentials - SCOPE = 'http://example.com/scope'.freeze - PATH_ENV_VARS = ['PATH_ENV_DUMMY', 'PATH_ENV_TEST'].freeze - JSON_ENV_VARS = ['JSON_ENV_DUMMY'].freeze - DEFAULT_PATHS = ['~/default/path/to/file.txt'].freeze + SCOPE = "http://example.com/scope".freeze + PATH_ENV_VARS = %w[PATH_ENV_DUMMY PATH_ENV_TEST].freeze + JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze + DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze end - allow(::ENV).to receive(:[]).with('PATH_ENV_DUMMY') { '/fake/path/to/file.txt' } - allow(::File).to receive(:file?).with('/fake/path/to/file.txt') { false } - allow(::ENV).to receive(:[]).with('PATH_ENV_TEST') { '/unknown/path/to/file.txt' } - allow(::File).to receive(:file?).with('/unknown/path/to/file.txt') { true } - allow(::File).to receive(:read).with('/unknown/path/to/file.txt') { JSON.generate(default_keyfile_hash) } + allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" } + allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false } + allow(::ENV).to receive(:[]).with("PATH_ENV_TEST") { "/unknown/path/to/file.txt" } + allow(::File).to receive(:file?).with("/unknown/path/to/file.txt") { true } + allow(::File).to receive(:read).with("/unknown/path/to/file.txt") { JSON.generate default_keyfile_hash } - mocked_signet = double('Signet::OAuth2::Client') + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -148,31 +148,31 @@ describe Google::Auth::Credentials, :private do creds = TestCredentials.default expect(creds).to be_a_kind_of(TestCredentials) expect(creds.client).to eq(mocked_signet) - expect(creds.project_id).to eq(default_keyfile_hash['project_id']) + expect(creds.project_id).to eq(default_keyfile_hash["project_id"]) end - it 'subclasses can use JSON_ENV_VARS to get keyfile contents' do + it "subclasses can use JSON_ENV_VARS to get keyfile contents" do class TestCredentials < Google::Auth::Credentials - SCOPE = 'http://example.com/scope'.freeze - PATH_ENV_VARS = ['PATH_ENV_DUMMY'].freeze - JSON_ENV_VARS = ['JSON_ENV_DUMMY', 'JSON_ENV_TEST'].freeze - DEFAULT_PATHS = ['~/default/path/to/file.txt'].freeze + SCOPE = "http://example.com/scope".freeze + PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze + JSON_ENV_VARS = %w[JSON_ENV_DUMMY JSON_ENV_TEST].freeze + DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze end - allow(::ENV).to receive(:[]).with('PATH_ENV_DUMMY') { '/fake/path/to/file.txt' } - allow(::File).to receive(:file?).with('/fake/path/to/file.txt') { false } - allow(::ENV).to receive(:[]).with('JSON_ENV_DUMMY') { nil } - allow(::ENV).to receive(:[]).with('JSON_ENV_TEST') { JSON.generate(default_keyfile_hash) } + allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" } + allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false } + allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil } + allow(::ENV).to receive(:[]).with("JSON_ENV_TEST") { JSON.generate default_keyfile_hash } - mocked_signet = double('Signet::OAuth2::Client') + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -181,32 +181,32 @@ describe Google::Auth::Credentials, :private do creds = TestCredentials.default expect(creds).to be_a_kind_of(TestCredentials) expect(creds.client).to eq(mocked_signet) - expect(creds.project_id).to eq(default_keyfile_hash['project_id']) + expect(creds.project_id).to eq(default_keyfile_hash["project_id"]) end - it 'subclasses can use DEFAULT_PATHS to get keyfile path' do + it "subclasses can use DEFAULT_PATHS to get keyfile path" do class TestCredentials < Google::Auth::Credentials - SCOPE = 'http://example.com/scope'.freeze - PATH_ENV_VARS = ['PATH_ENV_DUMMY'].freeze - JSON_ENV_VARS = ['JSON_ENV_DUMMY'].freeze - DEFAULT_PATHS = ['~/default/path/to/file.txt'].freeze + SCOPE = "http://example.com/scope".freeze + PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze + JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze + DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze end - allow(::ENV).to receive(:[]).with('PATH_ENV_DUMMY') { '/fake/path/to/file.txt' } - allow(::File).to receive(:file?).with('/fake/path/to/file.txt') { false } - allow(::ENV).to receive(:[]).with('JSON_ENV_DUMMY') { nil } - allow(::File).to receive(:file?).with('~/default/path/to/file.txt') { true } - allow(::File).to receive(:read).with('~/default/path/to/file.txt') { JSON.generate(default_keyfile_hash) } + allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" } + allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false } + allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil } + allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { true } + allow(::File).to receive(:read).with("~/default/path/to/file.txt") { JSON.generate default_keyfile_hash } - mocked_signet = double('Signet::OAuth2::Client') + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -215,23 +215,23 @@ describe Google::Auth::Credentials, :private do creds = TestCredentials.default expect(creds).to be_a_kind_of(TestCredentials) expect(creds.client).to eq(mocked_signet) - expect(creds.project_id).to eq(default_keyfile_hash['project_id']) + expect(creds.project_id).to eq(default_keyfile_hash["project_id"]) end - it 'subclasses that find no matches default to Google::Auth.get_application_default' do + it "subclasses that find no matches default to Google::Auth.get_application_default" do class TestCredentials < Google::Auth::Credentials - SCOPE = 'http://example.com/scope'.freeze - PATH_ENV_VARS = ['PATH_ENV_DUMMY'].freeze - JSON_ENV_VARS = ['JSON_ENV_DUMMY'].freeze - DEFAULT_PATHS = ['~/default/path/to/file.txt'].freeze + SCOPE = "http://example.com/scope".freeze + PATH_ENV_VARS = ["PATH_ENV_DUMMY"].freeze + JSON_ENV_VARS = ["JSON_ENV_DUMMY"].freeze + DEFAULT_PATHS = ["~/default/path/to/file.txt"].freeze end - allow(::ENV).to receive(:[]).with('PATH_ENV_DUMMY') { '/fake/path/to/file.txt' } - allow(::File).to receive(:file?).with('/fake/path/to/file.txt') { false } - allow(::ENV).to receive(:[]).with('JSON_ENV_DUMMY') { nil } - allow(::File).to receive(:file?).with('~/default/path/to/file.txt') { false } + allow(::ENV).to receive(:[]).with("PATH_ENV_DUMMY") { "/fake/path/to/file.txt" } + allow(::File).to receive(:file?).with("/fake/path/to/file.txt") { false } + allow(::ENV).to receive(:[]).with("JSON_ENV_DUMMY") { nil } + allow(::File).to receive(:file?).with("~/default/path/to/file.txt") { false } - mocked_signet = double('Signet::OAuth2::Client') + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) allow(mocked_signet).to receive(:client_id) @@ -243,10 +243,10 @@ describe Google::Auth::Credentials, :private do default_keyfile_hash end allow(Signet::OAuth2::Client).to receive(:new) do |options| - expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token') - expect(options[:audience]).to eq('https://oauth2.googleapis.com/token') - expect(options[:scope]).to eq(['http://example.com/scope']) - expect(options[:issuer]).to eq(default_keyfile_hash['client_email']) + expect(options[:token_credential_uri]).to eq("https://oauth2.googleapis.com/token") + expect(options[:audience]).to eq("https://oauth2.googleapis.com/token") + expect(options[:scope]).to eq(["http://example.com/scope"]) + expect(options[:issuer]).to eq(default_keyfile_hash["client_email"]) expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA) mocked_signet @@ -255,14 +255,14 @@ describe Google::Auth::Credentials, :private do creds = TestCredentials.default expect(creds).to be_a_kind_of(TestCredentials) expect(creds.client).to eq(mocked_signet) - expect(creds.project_id).to eq(default_keyfile_hash['project_id']) + expect(creds.project_id).to eq(default_keyfile_hash["project_id"]) end - it 'warns when cloud sdk credentials are used' do - mocked_signet = double('Signet::OAuth2::Client') + it "warns when cloud sdk credentials are used" do + mocked_signet = double "Signet::OAuth2::Client" allow(mocked_signet).to receive(:configure_connection).and_return(mocked_signet) allow(mocked_signet).to receive(:fetch_access_token!).and_return(true) - allow(Signet::OAuth2::Client).to receive(:new) do |options| + allow(Signet::OAuth2::Client).to receive(:new) do |_options| mocked_signet end allow(mocked_signet).to receive(:client_id).and_return(Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID) diff --git a/spec/googleauth/get_application_default_spec.rb b/spec/googleauth/get_application_default_spec.rb index 811a9a6..fc61ffb 100644 --- a/spec/googleauth/get_application_default_spec.rb +++ b/spec/googleauth/get_application_default_spec.rb @@ -27,22 +27,22 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'faraday' -require 'fakefs/safe' -require 'googleauth' -require 'spec_helper' -require 'os' +require "faraday" +require "fakefs/safe" +require "googleauth" +require "spec_helper" +require "os" -describe '#get_application_default' do +describe "#get_application_default" do # Pass unique options each time to bypass memoization let(:options) { |example| { dememoize: example } } - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) + before :example do + @key = OpenSSL::PKey::RSA.new 2048 @var_name = ENV_VAR @credential_vars = [ ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, CLIENT_ID_VAR, @@ -50,36 +50,36 @@ describe '#get_application_default' do ] @original_env_vals = {} @credential_vars.each { |var| @original_env_vals[var] = ENV[var] } - @home = ENV['HOME'] - @app_data = ENV['APPDATA'] - @program_data = ENV['ProgramData'] - @scope = 'https://www.googleapis.com/auth/userinfo.profile' + @home = ENV["HOME"] + @app_data = ENV["APPDATA"] + @program_data = ENV["ProgramData"] + @scope = "https://www.googleapis.com/auth/userinfo.profile" end - after(:example) do + after :example do @credential_vars.each { |var| ENV[var] = @original_env_vals[var] } - ENV['HOME'] = @home unless @home == ENV['HOME'] - ENV['APPDATA'] = @app_data unless @app_data == ENV['APPDATA'] - ENV['ProgramData'] = @program_data unless @program_data == ENV['ProgramData'] + ENV["HOME"] = @home unless @home == ENV["HOME"] + ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"] + ENV["ProgramData"] = @program_data unless @program_data == ENV["ProgramData"] end - shared_examples 'it cannot load misconfigured credentials' do - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist' do + shared_examples "it cannot load misconfigured credentials" do + it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'does-not-exist') + key_path = File.join dir, "does-not-exist" ENV[@var_name] = key_path expect { Google::Auth.get_application_default @scope, options } .to raise_error RuntimeError end end - it 'fails without default file or env if not on compute engine' do - stub = stub_request(:get, 'http://169.254.169.254') - .to_return(status: 404, - headers: { 'Metadata-Flavor' => 'NotGoogle' }) + it "fails without default file or env if not on compute engine" do + stub = stub_request(:get, "http://169.254.169.254") + .to_return(status: 404, + headers: { "Metadata-Flavor" => "NotGoogle" }) Dir.mktmpdir do |dir| - ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var - ENV['HOME'] = dir # no config present in this tmp dir + ENV.delete @var_name unless ENV[@var_name].nil? # no env var + ENV["HOME"] = dir # no config present in this tmp dir expect do Google::Auth.get_application_default @scope, options end.to raise_error RuntimeError @@ -88,12 +88,12 @@ describe '#get_application_default' do end end - shared_examples 'it can successfully load credentials' do - it 'succeeds if the GOOGLE_APPLICATION_CREDENTIALS file is valid' do + shared_examples "it can successfully load credentials" do + it "succeeds if the GOOGLE_APPLICATION_CREDENTIALS file is valid" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path expect(Google::Auth.get_application_default(@scope, options)) .to_not be_nil @@ -102,73 +102,73 @@ describe '#get_application_default' do it "propagates default_connection option" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path - connection = Faraday.new(headers: {"User-Agent" => "hello"}) - opts = options.merge(default_connection: connection) - creds = Google::Auth.get_application_default(@scope, opts) + connection = Faraday.new headers: { "User-Agent" => "hello" } + opts = options.merge default_connection: connection + creds = Google::Auth.get_application_default @scope, opts expect(creds.build_default_connection).to be connection end end - it 'succeeds with default file without GOOGLE_APPLICATION_CREDENTIALS' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "succeeds with default file without GOOGLE_APPLICATION_CREDENTIALS" do + ENV.delete @var_name unless ENV[@var_name].nil? Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', WELL_KNOWN_PATH) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", WELL_KNOWN_PATH + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect(Google::Auth.get_application_default(@scope, options)) .to_not be_nil end end - it 'succeeds with default file without a scope' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "succeeds with default file without a scope" do + ENV.delete @var_name unless ENV[@var_name].nil? Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', WELL_KNOWN_PATH) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", WELL_KNOWN_PATH + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect(Google::Auth.get_application_default(nil, options)).to_not be_nil end end - it 'succeeds without default file or env if on compute engine' do - stub = stub_request(:get, 'http://169.254.169.254') - .to_return(status: 200, - headers: { 'Metadata-Flavor' => 'Google' }) + it "succeeds without default file or env if on compute engine" do + stub = stub_request(:get, "http://169.254.169.254") + .to_return(status: 200, + headers: { "Metadata-Flavor" => "Google" }) Dir.mktmpdir do |dir| - ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var - ENV['HOME'] = dir # no config present in this tmp dir + ENV.delete @var_name unless ENV[@var_name].nil? # no env var + ENV["HOME"] = dir # no config present in this tmp dir creds = Google::Auth.get_application_default @scope, options expect(creds).to_not be_nil end expect(stub).to have_been_requested end - it 'succeeds with system default file' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "succeeds with system default file" do + ENV.delete @var_name unless ENV[@var_name].nil? FakeFS do - ENV['ProgramData'] = '/etc' - prefix = OS.windows? ? '/etc/Google/Auth/' : '/etc/google/auth/' - key_path = File.join(prefix, CREDENTIALS_FILE_NAME) - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + ENV["ProgramData"] = "/etc" + prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/" + key_path = File.join prefix, CREDENTIALS_FILE_NAME + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text expect(Google::Auth.get_application_default(@scope, options)) .to_not be_nil - File.delete(key_path) + File.delete key_path end end - it 'succeeds if environment vars are valid' do - ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var + it "succeeds if environment vars are valid" do + ENV.delete @var_name unless ENV[@var_name].nil? # no env var ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] ENV[CLIENT_ID_VAR] = cred_json[:client_id] @@ -179,79 +179,79 @@ describe '#get_application_default' do .to_not be_nil end - it 'warns when using cloud sdk credentials' do - ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var + it "warns when using cloud sdk credentials" do + ENV.delete @var_name unless ENV[@var_name].nil? # no env var ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] ENV[CLIENT_ID_VAR] = Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret] ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token] ENV[ACCOUNT_TYPE_VAR] = cred_json[:type] - ENV[PROJECT_ID_VAR] = 'a_project_id' + ENV[PROJECT_ID_VAR] = "a_project_id" expect { Google::Auth.get_application_default @scope, options }.to output( Google::Auth::CredentialsLoader::CLOUD_SDK_CREDENTIALS_WARNING + "\n" ).to_stderr end end - describe 'when credential type is service account' do - let(:cred_json) do + describe "when credential type is service account" do + let :cred_json do { - private_key_id: 'a_private_key_id', - private_key: @key.to_pem, - client_email: 'app@developer.gserviceaccount.com', - client_id: 'app.apps.googleusercontent.com', - type: 'service_account' + private_key_id: "a_private_key_id", + private_key: @key.to_pem, + client_email: "app@developer.gserviceaccount.com", + client_id: "app.apps.googleusercontent.com", + type: "service_account" } end def cred_json_text - MultiJson.dump(cred_json) + MultiJson.dump cred_json end - it_behaves_like 'it can successfully load credentials' - it_behaves_like 'it cannot load misconfigured credentials' + it_behaves_like "it can successfully load credentials" + it_behaves_like "it cannot load misconfigured credentials" end - describe 'when credential type is authorized_user' do - let(:cred_json) do + describe "when credential type is authorized_user" do + let :cred_json do { - client_secret: 'privatekey', - refresh_token: 'refreshtoken', - client_id: 'app.apps.googleusercontent.com', - type: 'authorized_user' + client_secret: "privatekey", + refresh_token: "refreshtoken", + client_id: "app.apps.googleusercontent.com", + type: "authorized_user" } end def cred_json_text - MultiJson.dump(cred_json) + MultiJson.dump cred_json end - it_behaves_like 'it can successfully load credentials' - it_behaves_like 'it cannot load misconfigured credentials' + it_behaves_like "it can successfully load credentials" + it_behaves_like "it cannot load misconfigured credentials" end - describe 'when credential type is unknown' do - let(:cred_json) do + describe "when credential type is unknown" do + let :cred_json do { - client_secret: 'privatekey', - refresh_token: 'refreshtoken', - client_id: 'app.apps.googleusercontent.com', - private_key: @key.to_pem, - client_email: 'app@developer.gserviceaccount.com', - type: 'not_known_type' + client_secret: "privatekey", + refresh_token: "refreshtoken", + client_id: "app.apps.googleusercontent.com", + private_key: @key.to_pem, + client_email: "app@developer.gserviceaccount.com", + type: "not_known_type" } end def cred_json_text - MultiJson.dump(cred_json) + MultiJson.dump cred_json end - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS file contains the creds' do + it "fails if the GOOGLE_APPLICATION_CREDENTIALS file contains the creds" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path expect do Google::Auth.get_application_default @scope, options @@ -259,22 +259,22 @@ describe '#get_application_default' do end end - it 'fails if the well known file contains the creds' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "fails if the well known file contains the creds" do + ENV.delete @var_name unless ENV[@var_name].nil? Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', WELL_KNOWN_PATH) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", WELL_KNOWN_PATH + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect do Google::Auth.get_application_default @scope, options end.to raise_error RuntimeError end end - it 'fails if env vars are set' do + it "fails if env vars are set" do ENV[ENV_VAR] = nil ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] diff --git a/spec/googleauth/iam_spec.rb b/spec/googleauth/iam_spec.rb index f7b2b3e..a3474cf 100644 --- a/spec/googleauth/iam_spec.rb +++ b/spec/googleauth/iam_spec.rb @@ -27,54 +27,54 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth/iam' +require "googleauth/iam" describe Google::Auth::IAMCredentials do IAMCredentials = Google::Auth::IAMCredentials - let(:test_selector) { 'the-test-selector' } - let(:test_token) { 'the-test-token' } - let(:test_creds) { IAMCredentials.new(test_selector, test_token) } + let(:test_selector) { "the-test-selector" } + let(:test_token) { "the-test-token" } + let(:test_creds) { IAMCredentials.new test_selector, test_token } - describe '#apply!' do - it 'should update the target hash with the iam values' do - md = { foo: 'bar' } - test_creds.apply!(md) + describe "#apply!" do + it "should update the target hash with the iam values" do + md = { foo: "bar" } + test_creds.apply! md expect(md[IAMCredentials::SELECTOR_KEY]).to eq test_selector expect(md[IAMCredentials::TOKEN_KEY]).to eq test_token - expect(md[:foo]).to eq 'bar' + expect(md[:foo]).to eq "bar" end end - describe 'updater_proc' do - it 'should provide a proc that updates a hash with the iam values' do - md = { foo: 'bar' } + describe "updater_proc" do + it "should provide a proc that updates a hash with the iam values" do + md = { foo: "bar" } the_proc = test_creds.updater_proc - got = the_proc.call(md) + got = the_proc.call md expect(got[IAMCredentials::SELECTOR_KEY]).to eq test_selector expect(got[IAMCredentials::TOKEN_KEY]).to eq test_token - expect(got[:foo]).to eq 'bar' + expect(got[:foo]).to eq "bar" end end - describe '#apply' do - it 'should not update the original hash with the iam values' do - md = { foo: 'bar' } - test_creds.apply(md) + describe "#apply" do + it "should not update the original hash with the iam values" do + md = { foo: "bar" } + test_creds.apply md expect(md[IAMCredentials::SELECTOR_KEY]).to be_nil expect(md[IAMCredentials::TOKEN_KEY]).to be_nil - expect(md[:foo]).to eq 'bar' + expect(md[:foo]).to eq "bar" end - it 'should return a with the iam values' do - md = { foo: 'bar' } - got = test_creds.apply(md) + it "should return a with the iam values" do + md = { foo: "bar" } + got = test_creds.apply md expect(got[IAMCredentials::SELECTOR_KEY]).to eq test_selector expect(got[IAMCredentials::TOKEN_KEY]).to eq test_token - expect(got[:foo]).to eq 'bar' + expect(got[:foo]).to eq "bar" end end end diff --git a/spec/googleauth/scope_util_spec.rb b/spec/googleauth/scope_util_spec.rb index d69b820..121e097 100644 --- a/spec/googleauth/scope_util_spec.rb +++ b/spec/googleauth/scope_util_spec.rb @@ -27,51 +27,51 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth/scope_util' +require "googleauth/scope_util" describe Google::Auth::ScopeUtil do - shared_examples 'normalizes scopes' do - let(:normalized) { Google::Auth::ScopeUtil.normalize(source) } + shared_examples "normalizes scopes" do + let(:normalized) { Google::Auth::ScopeUtil.normalize source } - it 'normalizes the email scope' do + it "normalizes the email scope" do expect(normalized).to include( - 'https://www.googleapis.com/auth/userinfo.email' + "https://www.googleapis.com/auth/userinfo.email" ) - expect(normalized).to_not include 'email' + expect(normalized).to_not include "email" end - it 'normalizes the profile scope' do + it "normalizes the profile scope" do expect(normalized).to include( - 'https://www.googleapis.com/auth/userinfo.profile' + "https://www.googleapis.com/auth/userinfo.profile" ) - expect(normalized).to_not include 'profile' + expect(normalized).to_not include "profile" end - it 'normalizes the openid scope' do - expect(normalized).to include 'https://www.googleapis.com/auth/plus.me' - expect(normalized).to_not include 'openid' + it "normalizes the openid scope" do + expect(normalized).to include "https://www.googleapis.com/auth/plus.me" + expect(normalized).to_not include "openid" end - it 'leaves other other scopes as-is' do - expect(normalized).to include 'https://www.googleapis.com/auth/drive' + it "leaves other other scopes as-is" do + expect(normalized).to include "https://www.googleapis.com/auth/drive" end end - context 'with scope as string' do - let(:source) do - 'email profile openid https://www.googleapis.com/auth/drive' + context "with scope as string" do + let :source do + "email profile openid https://www.googleapis.com/auth/drive" end - it_behaves_like 'normalizes scopes' + it_behaves_like "normalizes scopes" end - context 'with scope as Array' do - let(:source) do - %w(email profile openid https://www.googleapis.com/auth/drive) + context "with scope as Array" do + let :source do + %w[email profile openid https://www.googleapis.com/auth/drive] end - it_behaves_like 'normalizes scopes' + it_behaves_like "normalizes scopes" end end diff --git a/spec/googleauth/service_account_spec.rb b/spec/googleauth/service_account_spec.rb index 76a4cfc..950dd1c 100644 --- a/spec/googleauth/service_account_spec.rb +++ b/spec/googleauth/service_account_spec.rb @@ -27,81 +27,81 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'apply_auth_examples' -require 'fakefs/safe' -require 'fileutils' -require 'googleauth/service_account' -require 'jwt' -require 'multi_json' -require 'openssl' -require 'spec_helper' -require 'tmpdir' -require 'os' +require "apply_auth_examples" +require "fakefs/safe" +require "fileutils" +require "googleauth/service_account" +require "jwt" +require "multi_json" +require "openssl" +require "spec_helper" +require "tmpdir" +require "os" include Google::Auth::CredentialsLoader -shared_examples 'jwt header auth' do - context 'when jwt_aud_uri is present' do - let(:test_uri) { 'https://www.googleapis.com/myservice' } - let(:auth_prefix) { 'Bearer ' } +shared_examples "jwt header auth" do + context "when jwt_aud_uri is present" do + let(:test_uri) { "https://www.googleapis.com/myservice" } + let(:auth_prefix) { "Bearer " } let(:auth_key) { ServiceAccountJwtHeaderCredentials::AUTH_METADATA_KEY } let(:jwt_uri_key) { ServiceAccountJwtHeaderCredentials::JWT_AUD_URI_KEY } - def expect_is_encoded_jwt(hdr) + def expect_is_encoded_jwt hdr expect(hdr).to_not be_nil expect(hdr.start_with?(auth_prefix)).to be true authorization = hdr[auth_prefix.length..-1] - payload, = JWT.decode(authorization, @key.public_key, true, algorithm: 'RS256') - expect(payload['aud']).to eq(test_uri) - expect(payload['iss']).to eq(client_email) + payload, = JWT.decode authorization, @key.public_key, true, algorithm: "RS256" + expect(payload["aud"]).to eq(test_uri) + expect(payload["iss"]).to eq(client_email) end - describe '#apply!' do - it 'should update the target hash with a jwt token' do - md = { foo: 'bar' } + describe "#apply!" do + it "should update the target hash with a jwt token" do + md = { foo: "bar" } md[jwt_uri_key] = test_uri - @client.apply!(md) + @client.apply! md auth_header = md[auth_key] - expect_is_encoded_jwt(auth_header) + expect_is_encoded_jwt auth_header expect(md[jwt_uri_key]).to be_nil end end - describe 'updater_proc' do - it 'should provide a proc that updates a hash with a jwt token' do - md = { foo: 'bar' } + describe "updater_proc" do + it "should provide a proc that updates a hash with a jwt token" do + md = { foo: "bar" } md[jwt_uri_key] = test_uri the_proc = @client.updater_proc - got = the_proc.call(md) + got = the_proc.call md auth_header = got[auth_key] - expect_is_encoded_jwt(auth_header) + expect_is_encoded_jwt auth_header expect(got[jwt_uri_key]).to be_nil expect(md[jwt_uri_key]).to_not be_nil end end - describe '#apply' do - it 'should not update the original hash with a jwt token' do - md = { foo: 'bar' } + describe "#apply" do + it "should not update the original hash with a jwt token" do + md = { foo: "bar" } md[jwt_uri_key] = test_uri the_proc = @client.updater_proc - got = the_proc.call(md) + got = the_proc.call md auth_header = md[auth_key] expect(auth_header).to be_nil expect(got[jwt_uri_key]).to be_nil expect(md[jwt_uri_key]).to_not be_nil end - it 'should add a jwt token to the returned hash' do - md = { foo: 'bar' } + it "should add a jwt token to the returned hash" do + md = { foo: "bar" } md[jwt_uri_key] = test_uri - got = @client.apply(md) + got = @client.apply md auth_header = got[auth_key] - expect_is_encoded_jwt(auth_header) + expect_is_encoded_jwt auth_header end end end @@ -109,63 +109,63 @@ end describe Google::Auth::ServiceAccountCredentials do ServiceAccountCredentials = Google::Auth::ServiceAccountCredentials - let(:client_email) { 'app@developer.gserviceaccount.com' } - let(:cred_json) do + let(:client_email) { "app@developer.gserviceaccount.com" } + let :cred_json do { - private_key_id: 'a_private_key_id', - private_key: @key.to_pem, - client_email: client_email, - client_id: 'app.apps.googleusercontent.com', - type: 'service_account', - project_id: 'a_project_id' + private_key_id: "a_private_key_id", + private_key: @key.to_pem, + client_email: client_email, + client_id: "app.apps.googleusercontent.com", + type: "service_account", + project_id: "a_project_id" } end - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) + before :example do + @key = OpenSSL::PKey::RSA.new 2048 @client = ServiceAccountCredentials.make_creds( json_key_io: StringIO.new(cred_json_text), - scope: 'https://www.googleapis.com/auth/userinfo.profile' + scope: "https://www.googleapis.com/auth/userinfo.profile" ) end - def make_auth_stubs(opts = {}) - access_token = opts[:access_token] || '' - body = MultiJson.dump('access_token' => access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) + def make_auth_stubs opts = {} + access_token = opts[:access_token] || "" + body = MultiJson.dump("access_token" => access_token, + "token_type" => "Bearer", + "expires_in" => 3600) blk = proc do |request| - params = Addressable::URI.form_unencode(request.body) - _claim, _header = JWT.decode(params.assoc('assertion').last, + params = Addressable::URI.form_unencode request.body + _claim, _header = JWT.decode(params.assoc("assertion").last, @key.public_key, true, - algorithm: 'RS256') + algorithm: "RS256") end - stub_request(:post, 'https://www.googleapis.com/oauth2/v4/token') + stub_request(:post, "https://www.googleapis.com/oauth2/v4/token") .with(body: hash_including( - 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer' + "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer" ), &blk) - .to_return(body: body, - status: 200, - headers: { 'Content-Type' => 'application/json' }) + .to_return(body: body, + status: 200, + headers: { "Content-Type" => "application/json" }) end def cred_json_text - MultiJson.dump(cred_json) + MultiJson.dump cred_json end - it_behaves_like 'apply/apply! are OK' + it_behaves_like "apply/apply! are OK" - context 'when scope is nil' do - before(:example) do + context "when scope is nil" do + before :example do @client.scope = nil end - it_behaves_like 'jwt header auth' + it_behaves_like "jwt header auth" end - describe '#from_env' do - before(:example) do + describe "#from_env" do + before :example do @var_name = ENV_VAR @credential_vars = [ ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR @@ -174,56 +174,56 @@ describe Google::Auth::ServiceAccountCredentials do @credential_vars.each { |var| @original_env_vals[var] = ENV[var] } ENV[ACCOUNT_TYPE_VAR] = cred_json[:type] - @scope = 'https://www.googleapis.com/auth/userinfo.profile' + @scope = "https://www.googleapis.com/auth/userinfo.profile" @clz = ServiceAccountCredentials end - after(:example) do + after :example do @credential_vars.each { |var| ENV[var] = @original_env_vals[var] } end - it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(ServiceAccountCredentials.from_env(@scope)).to be_nil end - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(ServiceAccountCredentials.from_env(@scope)).to be_nil Dir.mktmpdir do |dir| - key_path = File.join(dir, 'does-not-exist') + key_path = File.join dir, "does-not-exist" ENV[@var_name] = key_path - expect { @clz.from_env(@scope) }.to raise_error RuntimeError + expect { @clz.from_env @scope }.to raise_error RuntimeError end end - it 'succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid' do + it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path expect(@clz.from_env(@scope)).to_not be_nil end end - it 'succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are'\ - ' valid' do + it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\ + " valid" do ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] expect(@clz.from_env(@scope)).to_not be_nil end - it 'sets project_id when the PROJECT_ID_VAR env var is set' do + it "sets project_id when the PROJECT_ID_VAR env var is set" do ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] ENV[PROJECT_ID_VAR] = cred_json[:project_id] ENV[ENV_VAR] = nil - credentials = @clz.from_env(@scope) + credentials = @clz.from_env @scope expect(credentials.project_id).to eq(cred_json[:project_id]) end - it 'succeeds when GOOGLE_PRIVATE_KEY is escaped' do + it "succeeds when GOOGLE_PRIVATE_KEY is escaped" do escaped_key = cred_json[:private_key].gsub "\n", '\n' ENV[PRIVATE_KEY_VAR] = "\"#{escaped_key}\"" ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] @@ -233,110 +233,110 @@ describe Google::Auth::ServiceAccountCredentials do it "propagates default_connection option" do ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] - connection = Faraday.new(headers: {"User-Agent" => "hello"}) - creds = @clz.from_env(@scope, default_connection: connection) + connection = Faraday.new headers: { "User-Agent" => "hello" } + creds = @clz.from_env @scope, default_connection: connection expect(creds.build_default_connection).to be connection end end - describe '#from_well_known_path' do - before(:example) do - @home = ENV['HOME'] - @app_data = ENV['APPDATA'] - @scope = 'https://www.googleapis.com/auth/userinfo.profile' + describe "#from_well_known_path" do + before :example do + @home = ENV["HOME"] + @app_data = ENV["APPDATA"] + @scope = "https://www.googleapis.com/auth/userinfo.profile" @known_path = WELL_KNOWN_PATH @clz = ServiceAccountCredentials end - after(:example) do - ENV['HOME'] = @home unless @home == ENV['HOME'] - ENV['APPDATA'] = @app_data unless @app_data == ENV['APPDATA'] + after :example do + ENV["HOME"] = @home unless @home == ENV["HOME"] + ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"] end - it 'is nil if no file exists' do - ENV['HOME'] = File.dirname(__FILE__) + it "is nil if no file exists" do + ENV["HOME"] = File.dirname __FILE__ expect(ServiceAccountCredentials.from_well_known_path(@scope)).to be_nil end - it 'successfully loads the file when it is present' do + it "successfully loads the file when it is present" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect(@clz.from_well_known_path(@scope)).to_not be_nil end end - it 'successfully sets project_id when file is present' do + it "successfully sets project_id when file is present" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir - credentials = @clz.from_well_known_path(@scope) + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir + credentials = @clz.from_well_known_path @scope expect(credentials.project_id).to eq(cred_json[:project_id]) end end it "propagates default_connection option" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir - connection = Faraday.new(headers: {"User-Agent" => "hello"}) - creds = @clz.from_well_known_path(@scope, default_connection: connection) + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir + connection = Faraday.new headers: { "User-Agent" => "hello" } + creds = @clz.from_well_known_path @scope, default_connection: connection expect(creds.build_default_connection).to be connection end end end - describe '#from_system_default_path' do - before(:example) do - @scope = 'https://www.googleapis.com/auth/userinfo.profile' - @program_data = ENV['ProgramData'] - @prefix = OS.windows? ? '/etc/Google/Auth/' : '/etc/google/auth/' - @path = File.join(@prefix, CREDENTIALS_FILE_NAME) + describe "#from_system_default_path" do + before :example do + @scope = "https://www.googleapis.com/auth/userinfo.profile" + @program_data = ENV["ProgramData"] + @prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/" + @path = File.join @prefix, CREDENTIALS_FILE_NAME @clz = ServiceAccountCredentials end - after(:example) do - ENV['ProgramData'] = @program_data + after :example do + ENV["ProgramData"] = @program_data end - it 'is nil if no file exists' do + it "is nil if no file exists" do FakeFS do expect(ServiceAccountCredentials.from_system_default_path(@scope)) .to be_nil end end - it 'successfully loads the file when it is present' do + it "successfully loads the file when it is present" do FakeFS do - ENV['ProgramData'] = '/etc' - FileUtils.mkdir_p(File.dirname(@path)) - File.write(@path, cred_json_text) + ENV["ProgramData"] = "/etc" + FileUtils.mkdir_p File.dirname(@path) + File.write @path, cred_json_text expect(@clz.from_system_default_path(@scope)).to_not be_nil - File.delete(@path) + File.delete @path end end it "propagates default_connection option" do FakeFS do - ENV['ProgramData'] = '/etc' - FileUtils.mkdir_p(File.dirname(@path)) - File.write(@path, cred_json_text) - connection = Faraday.new(headers: {"User-Agent" => "hello"}) - creds = @clz.from_system_default_path(@scope, default_connection: connection) + ENV["ProgramData"] = "/etc" + FileUtils.mkdir_p File.dirname(@path) + File.write @path, cred_json_text + connection = Faraday.new headers: { "User-Agent" => "hello" } + creds = @clz.from_system_default_path @scope, default_connection: connection expect(creds.build_default_connection).to be connection - File.delete(@path) + File.delete @path end end end @@ -346,32 +346,32 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do ServiceAccountJwtHeaderCredentials = Google::Auth::ServiceAccountJwtHeaderCredentials - let(:client_email) { 'app@developer.gserviceaccount.com' } + let(:client_email) { "app@developer.gserviceaccount.com" } let(:clz) { Google::Auth::ServiceAccountJwtHeaderCredentials } - let(:cred_json) do + let :cred_json do { - private_key_id: 'a_private_key_id', - private_key: @key.to_pem, - client_email: client_email, - client_id: 'app.apps.googleusercontent.com', - type: 'service_account', - project_id: 'a_project_id' + private_key_id: "a_private_key_id", + private_key: @key.to_pem, + client_email: client_email, + client_id: "app.apps.googleusercontent.com", + type: "service_account", + project_id: "a_project_id" } end - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) - @client = clz.make_creds(json_key_io: StringIO.new(cred_json_text)) + before :example do + @key = OpenSSL::PKey::RSA.new 2048 + @client = clz.make_creds json_key_io: StringIO.new(cred_json_text) end def cred_json_text - MultiJson.dump(cred_json) + MultiJson.dump cred_json end - it_behaves_like 'jwt header auth' + it_behaves_like "jwt header auth" - describe '#from_env' do - before(:example) do + describe "#from_env" do + before :example do @var_name = ENV_VAR @credential_vars = [ ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR @@ -381,90 +381,90 @@ describe Google::Auth::ServiceAccountJwtHeaderCredentials do ENV[ACCOUNT_TYPE_VAR] = cred_json[:type] end - after(:example) do + after :example do @credential_vars.each { |var| ENV[var] = @original_env_vals[var] } end - it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(clz.from_env).to be_nil end - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(clz.from_env).to be_nil Dir.mktmpdir do |dir| - key_path = File.join(dir, 'does-not-exist') + key_path = File.join dir, "does-not-exist" ENV[@var_name] = key_path expect { clz.from_env }.to raise_error RuntimeError end end - it 'succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid' do + it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path expect(clz.from_env).to_not be_nil end end - it 'succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are'\ - ' valid' do + it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\ + " valid" do ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] expect(clz.from_env(@scope)).to_not be_nil end - it 'sets project_id when the PROJECT_ID_VAR env var is set' do + it "sets project_id when the PROJECT_ID_VAR env var is set" do ENV[PRIVATE_KEY_VAR] = cred_json[:private_key] ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email] ENV[PROJECT_ID_VAR] = cred_json[:project_id] ENV[ENV_VAR] = nil - credentials = clz.from_env(@scope) + credentials = clz.from_env @scope expect(credentials).to_not be_nil expect(credentials.project_id).to eq(cred_json[:project_id]) end end - describe '#from_well_known_path' do - before(:example) do - @home = ENV['HOME'] - @app_data = ENV['APPDATA'] + describe "#from_well_known_path" do + before :example do + @home = ENV["HOME"] + @app_data = ENV["APPDATA"] end - after(:example) do - ENV['HOME'] = @home unless @home == ENV['HOME'] - ENV['APPDATA'] = @app_data unless @app_data == ENV['APPDATA'] + after :example do + ENV["HOME"] = @home unless @home == ENV["HOME"] + ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"] end - it 'is nil if no file exists' do - ENV['HOME'] = File.dirname(__FILE__) + it "is nil if no file exists" do + ENV["HOME"] = File.dirname __FILE__ expect(clz.from_well_known_path).to be_nil end - it 'successfully loads the file when it is present' do + it "successfully loads the file when it is present" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', WELL_KNOWN_PATH) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", WELL_KNOWN_PATH + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect(clz.from_well_known_path).to_not be_nil end end - it 'successfully sets project_id when file is present' do + it "successfully sets project_id when file is present" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', WELL_KNOWN_PATH) - key_path = File.join(dir, WELL_KNOWN_PATH) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir - credentials = clz.from_well_known_path(@scope) + key_path = File.join dir, ".config", WELL_KNOWN_PATH + key_path = File.join dir, WELL_KNOWN_PATH if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir + credentials = clz.from_well_known_path @scope expect(credentials.project_id).to eq(cred_json[:project_id]) end end diff --git a/spec/googleauth/signet_spec.rb b/spec/googleauth/signet_spec.rb index 0f52768..866d99d 100644 --- a/spec/googleauth/signet_spec.rb +++ b/spec/googleauth/signet_spec.rb @@ -27,61 +27,60 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'apply_auth_examples' -require 'googleauth/signet' -require 'jwt' -require 'openssl' -require 'spec_helper' +require "apply_auth_examples" +require "googleauth/signet" +require "jwt" +require "openssl" +require "spec_helper" describe Signet::OAuth2::Client do - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) + before :example do + @key = OpenSSL::PKey::RSA.new 2048 @client = Signet::OAuth2::Client.new( - token_credential_uri: 'https://oauth2.googleapis.com/token', - scope: 'https://www.googleapis.com/auth/userinfo.profile', - issuer: 'app@example.com', - audience: 'https://oauth2.googleapis.com/token', - signing_key: @key + token_credential_uri: "https://oauth2.googleapis.com/token", + scope: "https://www.googleapis.com/auth/userinfo.profile", + issuer: "app@example.com", + audience: "https://oauth2.googleapis.com/token", + signing_key: @key ) end - def make_auth_stubs(opts) - access_token = opts[:access_token] || '' - body = MultiJson.dump('access_token' => access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) + def make_auth_stubs opts + access_token = opts[:access_token] || "" + body = MultiJson.dump("access_token" => access_token, + "token_type" => "Bearer", + "expires_in" => 3600) blk = proc do |request| - params = Addressable::URI.form_unencode(request.body) - _claim, _header = JWT.decode(params.assoc('assertion').last, + params = Addressable::URI.form_unencode request.body + _claim, _header = JWT.decode(params.assoc("assertion").last, @key.public_key, true, - algorithm: 'RS256') + algorithm: "RS256") end - with_params = {body: hash_including( - "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer")} - if opts[:user_agent] - with_params[:headers] = {"User-Agent" => opts[:user_agent]} - end - stub_request(:post, 'https://oauth2.googleapis.com/token') + with_params = { body: hash_including( + "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer" + ) } + with_params[:headers] = { "User-Agent" => opts[:user_agent] } if opts[:user_agent] + stub_request(:post, "https://oauth2.googleapis.com/token") .with(with_params, &blk) - .to_return(body: body, - status: 200, - headers: { 'Content-Type' => 'application/json' }) + .to_return(body: body, + status: 200, + headers: { "Content-Type" => "application/json" }) end - it_behaves_like 'apply/apply! are OK' + it_behaves_like "apply/apply! are OK" describe "#configure_connection" do it "honors default_connection" do token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token, user_agent: "RubyRocks/1.0" - conn = Faraday.new headers: {"User-Agent" => "RubyRocks/1.0"} - @client.configure_connection(default_connection: conn) + conn = Faraday.new headers: { "User-Agent" => "RubyRocks/1.0" } + @client.configure_connection default_connection: conn md = { foo: "bar" } - @client.apply!(md) + @client.apply! md want = { foo: "bar", authorization: "Bearer #{token}" } expect(md).to eq(want) expect(stub).to have_been_requested @@ -91,11 +90,11 @@ describe Signet::OAuth2::Client do token = "1/abcdef1234567890" stub = make_auth_stubs access_token: token, user_agent: "RubyRocks/2.0" connection_builder = proc do - Faraday.new headers: {"User-Agent" => "RubyRocks/2.0"} + Faraday.new headers: { "User-Agent" => "RubyRocks/2.0" } end - @client.configure_connection(connection_builder: connection_builder) + @client.configure_connection connection_builder: connection_builder md = { foo: "bar" } - @client.apply!(md) + @client.apply! md want = { foo: "bar", authorization: "Bearer #{token}" } expect(md).to eq(want) expect(stub).to have_been_requested diff --git a/spec/googleauth/stores/file_token_store_spec.rb b/spec/googleauth/stores/file_token_store_spec.rb index 4ddca25..78da685 100644 --- a/spec/googleauth/stores/file_token_store_spec.rb +++ b/spec/googleauth/stores/file_token_store_spec.rb @@ -27,31 +27,31 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth' -require 'googleauth/stores/file_token_store' -require 'spec_helper' -require 'fakefs/safe' -require 'fakefs/spec_helpers' -require 'googleauth/stores/store_examples' +require "googleauth" +require "googleauth/stores/file_token_store" +require "spec_helper" +require "fakefs/safe" +require "fakefs/spec_helpers" +require "googleauth/stores/store_examples" module FakeFS class File # FakeFS doesn't implement. And since we don't need to actually lock, # just stub out... - def flock(*); end + def flock *; end end end describe Google::Auth::Stores::FileTokenStore do include FakeFS::SpecHelpers - let(:store) do - Google::Auth::Stores::FileTokenStore.new(file: '/tokens.yaml') + let :store do + Google::Auth::Stores::FileTokenStore.new file: "/tokens.yaml" end - it_behaves_like 'token store' + it_behaves_like "token store" end diff --git a/spec/googleauth/stores/redis_token_store_spec.rb b/spec/googleauth/stores/redis_token_store_spec.rb index 050322c..b3af197 100644 --- a/spec/googleauth/stores/redis_token_store_spec.rb +++ b/spec/googleauth/stores/redis_token_store_spec.rb @@ -27,24 +27,24 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth' -require 'googleauth/stores/redis_token_store' -require 'spec_helper' -require 'fakeredis/rspec' -require 'googleauth/stores/store_examples' +require "googleauth" +require "googleauth/stores/redis_token_store" +require "spec_helper" +require "fakeredis/rspec" +require "googleauth/stores/store_examples" describe Google::Auth::Stores::RedisTokenStore do - let(:redis) do + let :redis do Redis.new end - let(:store) do - Google::Auth::Stores::RedisTokenStore.new(redis: redis) + let :store do + Google::Auth::Stores::RedisTokenStore.new redis: redis end - it_behaves_like 'token store' + it_behaves_like "token store" end diff --git a/spec/googleauth/stores/store_examples.rb b/spec/googleauth/stores/store_examples.rb index deebf3f..e5e8a9b 100644 --- a/spec/googleauth/stores/store_examples.rb +++ b/spec/googleauth/stores/store_examples.rb @@ -27,32 +27,32 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'spec_helper' +require "spec_helper" -shared_examples 'token store' do - before(:each) do - store.store('default', 'test') +shared_examples "token store" do + before :each do + store.store "default", "test" end - it 'should return a stored value' do - expect(store.load('default')).to eq 'test' + it "should return a stored value" do + expect(store.load("default")).to eq "test" end - it 'should return nil for missing tokens' do - expect(store.load('notavalidkey')).to be_nil + it "should return nil for missing tokens" do + expect(store.load("notavalidkey")).to be_nil end - it 'should return nil for deleted tokens' do - store.delete('default') - expect(store.load('default')).to be_nil + it "should return nil for deleted tokens" do + store.delete "default" + expect(store.load("default")).to be_nil end - it 'should save overwrite values on store' do - store.store('default', 'test2') - expect(store.load('default')).to eq 'test2' + it "should save overwrite values on store" do + store.store "default", "test2" + expect(store.load("default")).to eq "test2" end end diff --git a/spec/googleauth/user_authorizer_spec.rb b/spec/googleauth/user_authorizer_spec.rb index 35665bc..5a36304 100644 --- a/spec/googleauth/user_authorizer_spec.rb +++ b/spec/googleauth/user_authorizer_spec.rb @@ -27,295 +27,294 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth' -require 'googleauth/user_authorizer' -require 'uri' -require 'multi_json' -require 'spec_helper' +require "googleauth" +require "googleauth/user_authorizer" +require "uri" +require "multi_json" +require "spec_helper" describe Google::Auth::UserAuthorizer do include TestHelpers - let(:client_id) { Google::Auth::ClientId.new('testclient', 'notasecret') } - let(:scope) { %w(email profile) } + let(:client_id) { Google::Auth::ClientId.new "testclient", "notasecret" } + let(:scope) { %w[email profile] } let(:token_store) { DummyTokenStore.new } - let(:callback_uri) { 'https://www.example.com/oauth/callback' } - let(:authorizer) do + let(:callback_uri) { "https://www.example.com/oauth/callback" } + let :authorizer do Google::Auth::UserAuthorizer.new(client_id, scope, token_store, callback_uri) end - shared_examples 'valid authorization url' do - it 'should have a valid base URI' do + shared_examples "valid authorization url" do + it "should have a valid base URI" do expect(uri).to match %r{https://accounts.google.com/o/oauth2/auth} end - it 'should request offline access' do + it "should request offline access" do expect(URI(uri).query).to match(/access_type=offline/) end - it 'should request response type code' do + it "should request response type code" do expect(URI(uri).query).to match(/response_type=code/) end - it 'should force approval' do + it "should force approval" do expect(URI(uri).query).to match(/approval_prompt=force/) end - it 'should include granted scopes' do + it "should include granted scopes" do expect(URI(uri).query).to match(/include_granted_scopes=true/) end - it 'should include the correct client id' do + it "should include the correct client id" do expect(URI(uri).query).to match(/client_id=testclient/) end - it 'should not include a client secret' do + it "should not include a client secret" do expect(URI(uri).query).to_not match(/client_secret/) end - it 'should include the callback uri' do + it "should include the callback uri" do expect(URI(uri).query).to match( %r{redirect_uri=https://www.example.com/oauth/callback} ) end - it 'should include the scope' do + it "should include the scope" do expect(URI(uri).query).to match(/scope=email%20profile/) end end - context 'when generating authorization URLs with user ID & state' do - let(:uri) do - authorizer.get_authorization_url(login_hint: 'user1', state: 'mystate') + context "when generating authorization URLs with user ID & state" do + let :uri do + authorizer.get_authorization_url login_hint: "user1", state: "mystate" end - it_behaves_like 'valid authorization url' + it_behaves_like "valid authorization url" - it 'includes a login hint' do + it "includes a login hint" do expect(URI(uri).query).to match(/login_hint=user1/) end - it 'includes the app state' do + it "includes the app state" do expect(URI(uri).query).to match(/state=mystate/) end end - context 'when generating authorization URLs with user ID and no state' do - let(:uri) { authorizer.get_authorization_url(login_hint: 'user1') } + context "when generating authorization URLs with user ID and no state" do + let(:uri) { authorizer.get_authorization_url login_hint: "user1" } - it_behaves_like 'valid authorization url' + it_behaves_like "valid authorization url" - it 'includes a login hint' do + it "includes a login hint" do expect(URI(uri).query).to match(/login_hint=user1/) end - it 'does not include the state parameter' do + it "does not include the state parameter" do expect(URI(uri).query).to_not match(/state/) end end - context 'when generating authorization URLs with no user ID and no state' do + context "when generating authorization URLs with no user ID and no state" do let(:uri) { authorizer.get_authorization_url } - it_behaves_like 'valid authorization url' + it_behaves_like "valid authorization url" - it 'does not include the login hint parameter' do + it "does not include the login hint parameter" do expect(URI(uri).query).to_not match(/login_hint/) end - it 'does not include the state parameter' do + it "does not include the state parameter" do expect(URI(uri).query).to_not match(/state/) end end - context 'when retrieving tokens' do - let(:token_json) do + context "when retrieving tokens" do + let :token_json do MultiJson.dump( - access_token: 'accesstoken', - refresh_token: 'refreshtoken', + access_token: "accesstoken", + refresh_token: "refreshtoken", expiration_time_millis: 1_441_234_742_000 ) end - context 'with a valid user id' do - let(:credentials) do - token_store.store('user1', token_json) - authorizer.get_credentials('user1') + context "with a valid user id" do + let :credentials do + token_store.store "user1", token_json + authorizer.get_credentials "user1" end - it 'should return an instance of UserRefreshCredentials' do + it "should return an instance of UserRefreshCredentials" do expect(credentials).to be_instance_of( Google::Auth::UserRefreshCredentials ) end - it 'should return credentials with a valid refresh token' do - expect(credentials.refresh_token).to eq 'refreshtoken' + it "should return credentials with a valid refresh token" do + expect(credentials.refresh_token).to eq "refreshtoken" end - it 'should return credentials with a valid access token' do - expect(credentials.access_token).to eq 'accesstoken' + it "should return credentials with a valid access token" do + expect(credentials.access_token).to eq "accesstoken" end - it 'should return credentials with a valid client ID' do - expect(credentials.client_id).to eq 'testclient' + it "should return credentials with a valid client ID" do + expect(credentials.client_id).to eq "testclient" end - it 'should return credentials with a valid client secret' do - expect(credentials.client_secret).to eq 'notasecret' + it "should return credentials with a valid client secret" do + expect(credentials.client_secret).to eq "notasecret" end - it 'should return credentials with a valid scope' do - expect(credentials.scope).to eq %w(email profile) + it "should return credentials with a valid scope" do + expect(credentials.scope).to eq %w[email profile] end - it 'should return credentials with a valid expiration time' do + it "should return credentials with a valid expiration time" do expect(credentials.expires_at).to eq Time.at(1_441_234_742) end end - context 'with an invalid user id' do - it 'should return nil' do - expect(authorizer.get_credentials('notauser')).to be_nil + context "with an invalid user id" do + it "should return nil" do + expect(authorizer.get_credentials("notauser")).to be_nil end end end - context 'when saving tokens' do + context "when saving tokens" do let(:expiry) { Time.now.to_i } - let(:credentials) do + let :credentials do Google::Auth::UserRefreshCredentials.new( - client_id: client_id.id, + client_id: client_id.id, client_secret: client_id.secret, - scope: scope, - refresh_token: 'refreshtoken', - access_token: 'accesstoken', - expires_at: expiry + scope: scope, + refresh_token: "refreshtoken", + access_token: "accesstoken", + expires_at: expiry ) end - let(:token_json) do - authorizer.store_credentials('user1', credentials) - token_store.load('user1') + let :token_json do + authorizer.store_credentials "user1", credentials + token_store.load "user1" end - it 'should persist in the token store' do + it "should persist in the token store" do expect(token_json).to_not be_nil end - it 'should persist the refresh token' do - expect(MultiJson.load(token_json)['refresh_token']).to eq 'refreshtoken' + it "should persist the refresh token" do + expect(MultiJson.load(token_json)["refresh_token"]).to eq "refreshtoken" end - it 'should persist the access token' do - expect(MultiJson.load(token_json)['access_token']).to eq 'accesstoken' + it "should persist the access token" do + expect(MultiJson.load(token_json)["access_token"]).to eq "accesstoken" end - it 'should persist the client id' do - expect(MultiJson.load(token_json)['client_id']).to eq 'testclient' + it "should persist the client id" do + expect(MultiJson.load(token_json)["client_id"]).to eq "testclient" end - it 'should persist the scope' do - expect(MultiJson.load(token_json)['scope']).to include('email', 'profile') + it "should persist the scope" do + expect(MultiJson.load(token_json)["scope"]).to include("email", "profile") end - it 'should persist the expiry as milliseconds' do + it "should persist the expiry as milliseconds" do expected_expiry = expiry * 1000 - expect(MultiJson.load(token_json)['expiration_time_millis']).to eql( + expect(MultiJson.load(token_json)["expiration_time_millis"]).to eql( expected_expiry ) end end - context 'with valid authorization code' do - let(:token_json) do - MultiJson.dump('access_token' => '1/abc123', - 'token_type' => 'Bearer', - 'expires_in' => 3600) + context "with valid authorization code" do + let :token_json do + MultiJson.dump("access_token" => "1/abc123", + "token_type" => "Bearer", + "expires_in" => 3600) end - before(:example) do - stub_request(:post, 'https://oauth2.googleapis.com/token') + before :example do + stub_request(:post, "https://oauth2.googleapis.com/token") .to_return(body: token_json, status: 200, headers: { - 'Content-Type' => 'application/json' + "Content-Type" => "application/json" }) end - it 'should exchange a code for credentials' do + it "should exchange a code for credentials" do credentials = authorizer.get_credentials_from_code( - user_id: 'user1', code: 'code' + user_id: "user1", code: "code" ) - expect(credentials.access_token).to eq '1/abc123' + expect(credentials.access_token).to eq "1/abc123" end - it 'should not store credentials when get only requested' do - authorizer.get_credentials_from_code(user_id: 'user1', code: 'code') - expect(token_store.load('user1')).to be_nil + it "should not store credentials when get only requested" do + authorizer.get_credentials_from_code user_id: "user1", code: "code" + expect(token_store.load("user1")).to be_nil end - it 'should store credentials when requested' do + it "should store credentials when requested" do authorizer.get_and_store_credentials_from_code( - user_id: 'user1', code: 'code' + user_id: "user1", code: "code" ) - expect(token_store.load('user1')).to_not be_nil + expect(token_store.load("user1")).to_not be_nil end end - context 'with invalid authorization code' do - before(:example) do - stub_request(:post, 'https://oauth2.googleapis.com/token') + context "with invalid authorization code" do + before :example do + stub_request(:post, "https://oauth2.googleapis.com/token") .to_return(status: 400) end - it 'should raise an authorization error' do + it "should raise an authorization error" do expect do - authorizer.get_credentials_from_code(user_id: 'user1', code: 'badcode') + authorizer.get_credentials_from_code user_id: "user1", code: "badcode" end.to raise_error Signet::AuthorizationError end - it 'should not store credentials when exchange fails' do + it "should not store credentials when exchange fails" do expect do - authorizer.get_credentials_from_code(user_id: 'user1', code: 'badcode') + authorizer.get_credentials_from_code user_id: "user1", code: "badcode" end.to raise_error Signet::AuthorizationError - expect(token_store.load('user1')).to be_nil + expect(token_store.load("user1")).to be_nil end end - context 'when reovking authorization' do - let(:token_json) do + context "when reovking authorization" do + let :token_json do MultiJson.dump( - access_token: 'accesstoken', - refresh_token: 'refreshtoken', + access_token: "accesstoken", + refresh_token: "refreshtoken", expiration_time_millis: 1_441_234_742_000 ) end - before(:example) do - token_store.store('user1', token_json) - stub_request(:post, 'https://oauth2.googleapis.com/revoke') - .with(body: hash_including('token' => 'refreshtoken')) + before :example do + token_store.store "user1", token_json + stub_request(:post, "https://oauth2.googleapis.com/revoke") + .with(body: hash_including("token" => "refreshtoken")) .to_return(status: 200) end - it 'should revoke the grant' do - authorizer.revoke_authorization('user1') + it "should revoke the grant" do + authorizer.revoke_authorization "user1" expect(a_request( - :post, 'https://oauth2.googleapis.com/revoke' - ).with(body: hash_including('token' => 'refreshtoken')) - ) + :post, "https://oauth2.googleapis.com/revoke" + ).with(body: hash_including("token" => "refreshtoken"))) .to have_been_made end - it 'should remove the token from storage' do - authorizer.revoke_authorization('user1') - expect(token_store.load('user1')).to be_nil + it "should remove the token from storage" do + authorizer.revoke_authorization "user1" + expect(token_store.load("user1")).to be_nil end end diff --git a/spec/googleauth/user_refresh_spec.rb b/spec/googleauth/user_refresh_spec.rb index d38ca53..5deff95 100644 --- a/spec/googleauth/user_refresh_spec.rb +++ b/spec/googleauth/user_refresh_spec.rb @@ -27,64 +27,64 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'apply_auth_examples' -require 'fakefs/safe' -require 'fileutils' -require 'googleauth/user_refresh' -require 'jwt' -require 'multi_json' -require 'openssl' -require 'spec_helper' -require 'tmpdir' -require 'os' +require "apply_auth_examples" +require "fakefs/safe" +require "fileutils" +require "googleauth/user_refresh" +require "jwt" +require "multi_json" +require "openssl" +require "spec_helper" +require "tmpdir" +require "os" include Google::Auth::CredentialsLoader describe Google::Auth::UserRefreshCredentials do UserRefreshCredentials = Google::Auth::UserRefreshCredentials - let(:cred_json) do + let :cred_json do { - client_secret: 'privatekey', - client_id: 'client123', - refresh_token: 'refreshtoken', - type: 'authorized_user' + client_secret: "privatekey", + client_id: "client123", + refresh_token: "refreshtoken", + type: "authorized_user" } end - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) + before :example do + @key = OpenSSL::PKey::RSA.new 2048 @client = UserRefreshCredentials.make_creds( json_key_io: StringIO.new(cred_json_text), - scope: 'https://www.googleapis.com/auth/userinfo.profile' + scope: "https://www.googleapis.com/auth/userinfo.profile" ) end - def make_auth_stubs(opts = {}) - access_token = opts[:access_token] || '' - body = MultiJson.dump('access_token' => access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) - stub_request(:post, 'https://oauth2.googleapis.com/token') - .with(body: hash_including('grant_type' => 'refresh_token')) - .to_return(body: body, - status: 200, - headers: { 'Content-Type' => 'application/json' }) + def make_auth_stubs opts = {} + access_token = opts[:access_token] || "" + body = MultiJson.dump("access_token" => access_token, + "token_type" => "Bearer", + "expires_in" => 3600) + stub_request(:post, "https://oauth2.googleapis.com/token") + .with(body: hash_including("grant_type" => "refresh_token")) + .to_return(body: body, + status: 200, + headers: { "Content-Type" => "application/json" }) end - def cred_json_text(missing = nil) - cred_json.delete(missing.to_sym) unless missing.nil? - MultiJson.dump(cred_json) + def cred_json_text missing = nil + cred_json.delete missing.to_sym unless missing.nil? + MultiJson.dump cred_json end - it_behaves_like 'apply/apply! are OK' + it_behaves_like "apply/apply! are OK" - describe '#from_env' do - before(:example) do + describe "#from_env" do + before :example do @var_name = ENV_VAR @credential_vars = [ ENV_VAR, CLIENT_ID_VAR, CLIENT_SECRET_VAR, REFRESH_TOKEN_VAR, @@ -92,243 +92,243 @@ describe Google::Auth::UserRefreshCredentials do ] @original_env_vals = {} @credential_vars.each { |var| @original_env_vals[var] = ENV[var] } - @scope = 'https://www.googleapis.com/auth/userinfo.profile' + @scope = "https://www.googleapis.com/auth/userinfo.profile" @clz = UserRefreshCredentials - @project_id = 'a_project_id' + @project_id = "a_project_id" end - after(:example) do + after :example do @credential_vars.each { |var| ENV[var] = @original_env_vals[var] } end - it 'returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(UserRefreshCredentials.from_env(@scope)).to be_nil end - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist' do - ENV.delete(@var_name) unless ENV[@var_name].nil? + it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do + ENV.delete @var_name unless ENV[@var_name].nil? expect(UserRefreshCredentials.from_env(@scope)).to be_nil Dir.mktmpdir do |dir| - key_path = File.join(dir, 'does-not-exist') + key_path = File.join dir, "does-not-exist" ENV[@var_name] = key_path - expect { @clz.from_env(@scope) }.to raise_error RuntimeError + expect { @clz.from_env @scope }.to raise_error RuntimeError end end - it 'fails if the GOOGLE_APPLICATION_CREDENTIALS path file is invalid' do - needed = %w(client_id client_secret refresh_token) + it "fails if the GOOGLE_APPLICATION_CREDENTIALS path file is invalid" do + needed = %w[client_id client_secret refresh_token] needed.each do |missing| Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text(missing)) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text(missing) ENV[@var_name] = key_path - expect { @clz.from_env(@scope) }.to raise_error RuntimeError + expect { @clz.from_env @scope }.to raise_error RuntimeError end end end - it 'succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid' do + it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do Dir.mktmpdir do |dir| - key_path = File.join(dir, 'my_cert_file') - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) + key_path = File.join dir, "my_cert_file" + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text ENV[@var_name] = key_path expect(@clz.from_env(@scope)).to_not be_nil end end - it 'succeeds when GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and '\ - 'GOOGLE_REFRESH_TOKEN env vars are valid' do + it "succeeds when GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and "\ + "GOOGLE_REFRESH_TOKEN env vars are valid" do ENV[ENV_VAR] = nil ENV[CLIENT_ID_VAR] = cred_json[:client_id] ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret] ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token] ENV[ACCOUNT_TYPE_VAR] = cred_json[:type] - creds = @clz.from_env(@scope) + creds = @clz.from_env @scope expect(creds).to_not be_nil expect(creds.client_id).to eq(cred_json[:client_id]) expect(creds.client_secret).to eq(cred_json[:client_secret]) expect(creds.refresh_token).to eq(cred_json[:refresh_token]) end - it 'sets project_id when the PROJECT_ID_VAR env var is set' do + it "sets project_id when the PROJECT_ID_VAR env var is set" do ENV[ENV_VAR] = nil ENV[CLIENT_ID_VAR] = cred_json[:client_id] ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret] ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token] ENV[ACCOUNT_TYPE_VAR] = cred_json[:type] ENV[PROJECT_ID_VAR] = @project_id - creds = @clz.from_env(@scope) + creds = @clz.from_env @scope expect(creds.project_id).to eq(@project_id) end end - describe '#from_well_known_path' do - before(:example) do - @home = ENV['HOME'] - @app_data = ENV['APPDATA'] - @scope = 'https://www.googleapis.com/auth/userinfo.profile' + describe "#from_well_known_path" do + before :example do + @home = ENV["HOME"] + @app_data = ENV["APPDATA"] + @scope = "https://www.googleapis.com/auth/userinfo.profile" @known_path = WELL_KNOWN_PATH @clz = UserRefreshCredentials end - after(:example) do - ENV['HOME'] = @home unless @home == ENV['HOME'] - ENV['APPDATA'] = @app_data unless @app_data == ENV['APPDATA'] + after :example do + ENV["HOME"] = @home unless @home == ENV["HOME"] + ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"] end - it 'is nil if no file exists' do - ENV['HOME'] = File.dirname(__FILE__) + it "is nil if no file exists" do + ENV["HOME"] = File.dirname __FILE__ expect(UserRefreshCredentials.from_well_known_path(@scope)).to be_nil end - it 'fails if the file is invalid' do - needed = %w(client_id client_secret refresh_token) + it "fails if the file is invalid" do + needed = %w[client_id client_secret refresh_token] needed.each do |missing| Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, @known_path) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text(missing)) - ENV['HOME'] = dir - ENV['APPDATA'] = dir - expect { @clz.from_well_known_path(@scope) } + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, @known_path if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text(missing) + ENV["HOME"] = dir + ENV["APPDATA"] = dir + expect { @clz.from_well_known_path @scope } .to raise_error RuntimeError end end end - it 'successfully loads the file when it is present' do + it "successfully loads the file when it is present" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, @known_path) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, @known_path if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir expect(@clz.from_well_known_path(@scope)).to_not be_nil end end - it 'checks gcloud config for project_id if none was provided' do + it "checks gcloud config for project_id if none was provided" do Dir.mktmpdir do |dir| - key_path = File.join(dir, '.config', @known_path) - key_path = File.join(dir, @known_path) if OS.windows? - FileUtils.mkdir_p(File.dirname(key_path)) - File.write(key_path, cred_json_text) - ENV['HOME'] = dir - ENV['APPDATA'] = dir + key_path = File.join dir, ".config", @known_path + key_path = File.join dir, @known_path if OS.windows? + FileUtils.mkdir_p File.dirname(key_path) + File.write key_path, cred_json_text + ENV["HOME"] = dir + ENV["APPDATA"] = dir ENV[PROJECT_ID_VAR] = nil expect(Google::Auth::CredentialsLoader).to receive(:load_gcloud_project_id).with(no_args) - @clz.from_well_known_path(@scope) + @clz.from_well_known_path @scope end end end - describe '#from_system_default_path' do - before(:example) do - @scope = 'https://www.googleapis.com/auth/userinfo.profile' - @prefix = OS.windows? ? '/etc/Google/Auth/' : '/etc/google/auth/' - @path = File.join(@prefix, CREDENTIALS_FILE_NAME) - @program_data = ENV['ProgramData'] + describe "#from_system_default_path" do + before :example do + @scope = "https://www.googleapis.com/auth/userinfo.profile" + @prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/" + @path = File.join @prefix, CREDENTIALS_FILE_NAME + @program_data = ENV["ProgramData"] @clz = UserRefreshCredentials end - after(:example) do - ENV['ProgramData'] = @program_data + after :example do + ENV["ProgramData"] = @program_data end - it 'is nil if no file exists' do + it "is nil if no file exists" do FakeFS do expect(UserRefreshCredentials.from_system_default_path(@scope)) .to be_nil end end - it 'fails if the file is invalid' do - needed = %w(client_id client_secret refresh_token) + it "fails if the file is invalid" do + needed = %w[client_id client_secret refresh_token] needed.each do |missing| FakeFS do - ENV['ProgramData'] = '/etc' - FileUtils.mkdir_p(File.dirname(@path)) - File.write(@path, cred_json_text(missing)) - expect { @clz.from_system_default_path(@scope) } + ENV["ProgramData"] = "/etc" + FileUtils.mkdir_p File.dirname(@path) + File.write @path, cred_json_text(missing) + expect { @clz.from_system_default_path @scope } .to raise_error RuntimeError - File.delete(@path) + File.delete @path end end end - it 'successfully loads the file when it is present' do + it "successfully loads the file when it is present" do FakeFS do - ENV['ProgramData'] = '/etc' - FileUtils.mkdir_p(File.dirname(@path)) - File.write(@path, cred_json_text) + ENV["ProgramData"] = "/etc" + FileUtils.mkdir_p File.dirname(@path) + File.write @path, cred_json_text expect(@clz.from_system_default_path(@scope)).to_not be_nil - File.delete(@path) + File.delete @path end end end - shared_examples 'revoked token' do - it 'should nil the refresh token' do + shared_examples "revoked token" do + it "should nil the refresh token" do expect(@client.refresh_token).to be_nil end - it 'should nil the access token' do + it "should nil the access token" do expect(@client.access_token).to be_nil end - it 'should mark the token as expired' do + it "should mark the token as expired" do expect(@client.expired?).to be_truthy end end - describe 'when revoking a refresh token' do - let(:stub) do - stub_request(:post, 'https://oauth2.googleapis.com/revoke') - .with(body: hash_including('token' => 'refreshtoken')) - .to_return(status: 200, - headers: { 'Content-Type' => 'application/json' }) + describe "when revoking a refresh token" do + let :stub do + stub_request(:post, "https://oauth2.googleapis.com/revoke") + .with(body: hash_including("token" => "refreshtoken")) + .to_return(status: 200, + headers: { "Content-Type" => "application/json" }) end - before(:example) do + before :example do stub @client.revoke! end - it_behaves_like 'revoked token' + it_behaves_like "revoked token" end - describe 'when revoking an access token' do - let(:stub) do - stub_request(:post, 'https://oauth2.googleapis.com/revoke') - .with(body: hash_including('token' => 'accesstoken')) - .to_return(status: 200, - headers: { 'Content-Type' => 'application/json' }) + describe "when revoking an access token" do + let :stub do + stub_request(:post, "https://oauth2.googleapis.com/revoke") + .with(body: hash_including("token" => "accesstoken")) + .to_return(status: 200, + headers: { "Content-Type" => "application/json" }) end - before(:example) do + before :example do stub @client.refresh_token = nil - @client.access_token = 'accesstoken' + @client.access_token = "accesstoken" @client.revoke! end - it_behaves_like 'revoked token' + it_behaves_like "revoked token" end - describe 'when revoking an invalid token' do - let(:stub) do - stub_request(:post, 'https://oauth2.googleapis.com/revoke') - .with(body: hash_including('token' => 'refreshtoken')) - .to_return(status: 400, - headers: { 'Content-Type' => 'application/json' }) + describe "when revoking an invalid token" do + let :stub do + stub_request(:post, "https://oauth2.googleapis.com/revoke") + .with(body: hash_including("token" => "refreshtoken")) + .to_return(status: 400, + headers: { "Content-Type" => "application/json" }) end - it 'raises an authorization error' do + it "raises an authorization error" do stub expect { @client.revoke! }.to raise_error( Signet::AuthorizationError @@ -336,15 +336,15 @@ describe Google::Auth::UserRefreshCredentials do end end - describe 'when errors occurred with request' do - it 'should fail with Signet::AuthorizationError if request times out' do + describe "when errors occurred with request" do + it "should fail with Signet::AuthorizationError if request times out" do allow_any_instance_of(Faraday::Connection).to receive(:post) .and_raise(Faraday::TimeoutError) expect { @client.revoke! } .to raise_error Signet::AuthorizationError end - it 'should fail with Signet::AuthorizationError if request fails' do + it "should fail with Signet::AuthorizationError if request fails" do allow_any_instance_of(Faraday::Connection).to receive(:post) .and_raise(Faraday::ConnectionFailed, nil) expect { @client.revoke! } diff --git a/spec/googleauth/web_user_authorizer_spec.rb b/spec/googleauth/web_user_authorizer_spec.rb index b26cc66..6d299cd 100644 --- a/spec/googleauth/web_user_authorizer_spec.rb +++ b/spec/googleauth/web_user_authorizer_spec.rb @@ -27,140 +27,140 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) +spec_dir = File.expand_path File.join(File.dirname(__FILE__)) +$LOAD_PATH.unshift spec_dir $LOAD_PATH.uniq! -require 'googleauth' -require 'googleauth/web_user_authorizer' -require 'uri' -require 'multi_json' -require 'spec_helper' -require 'rack' +require "googleauth" +require "googleauth/web_user_authorizer" +require "uri" +require "multi_json" +require "spec_helper" +require "rack" describe Google::Auth::WebUserAuthorizer do include TestHelpers - let(:client_id) { Google::Auth::ClientId.new('testclient', 'notasecret') } - let(:scope) { %w(email profile) } + let(:client_id) { Google::Auth::ClientId.new "testclient", "notasecret" } + let(:scope) { %w[email profile] } let(:token_store) { DummyTokenStore.new } - let(:authorizer) do - Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store) + let :authorizer do + Google::Auth::WebUserAuthorizer.new client_id, scope, token_store end - describe '#get_authorization_url' do - let(:env) do + describe "#get_authorization_url" do + let :env do Rack::MockRequest.env_for( - 'http://example.com:8080/test', - 'REMOTE_ADDR' => '10.10.10.10' + "http://example.com:8080/test", + "REMOTE_ADDR" => "10.10.10.10" ) end - let(:request) { Rack::Request.new(env) } - it 'should include current url in state' do - url = authorizer.get_authorization_url(request: request) + let(:request) { Rack::Request.new env } + it "should include current url in state" do + url = authorizer.get_authorization_url request: request expect(url).to match( %r{%22current_uri%22:%22http://example.com:8080/test%22} ) end - it 'should include request forgery token in state' do - expect(SecureRandom).to receive(:base64).and_return('aGVsbG8=') - url = authorizer.get_authorization_url(request: request) + it "should include request forgery token in state" do + expect(SecureRandom).to receive(:base64).and_return("aGVsbG8=") + url = authorizer.get_authorization_url request: request expect(url).to match(/%22session_id%22:%22aGVsbG8=%22/) end - it 'should include request forgery token in session' do - expect(SecureRandom).to receive(:base64).and_return('aGVsbG8=') - authorizer.get_authorization_url(request: request) - expect(request.session['g-xsrf-token']).to eq 'aGVsbG8=' + it "should include request forgery token in session" do + expect(SecureRandom).to receive(:base64).and_return("aGVsbG8=") + authorizer.get_authorization_url request: request + expect(request.session["g-xsrf-token"]).to eq "aGVsbG8=" end - it 'should resolve callback against base URL' do - url = authorizer.get_authorization_url(request: request) + it "should resolve callback against base URL" do + url = authorizer.get_authorization_url request: request expect(url).to match( %r{redirect_uri=http://example.com:8080/oauth2callback} ) end - it 'should allow overriding the current URL' do + it "should allow overriding the current URL" do url = authorizer.get_authorization_url( - request: request, - redirect_to: '/foo' + request: request, + redirect_to: "/foo" ) expect(url).to match %r{%22current_uri%22:%22/foo%22} end - it 'should pass through login hint' do + it "should pass through login hint" do url = authorizer.get_authorization_url( - request: request, - login_hint: 'user@example.com' + request: request, + login_hint: "user@example.com" ) expect(url).to match(/login_hint=user@example.com/) end end - shared_examples 'handles callback' do - let(:token_json) do - MultiJson.dump('access_token' => '1/abc123', - 'token_type' => 'Bearer', - 'expires_in' => 3600) + shared_examples "handles callback" do + let :token_json do + MultiJson.dump("access_token" => "1/abc123", + "token_type" => "Bearer", + "expires_in" => 3600) end - before(:example) do - stub_request(:post, 'https://oauth2.googleapis.com/token') - .to_return(body: token_json, - status: 200, - headers: { 'Content-Type' => 'application/json' }) + before :example do + stub_request(:post, "https://oauth2.googleapis.com/token") + .to_return(body: token_json, + status: 200, + headers: { "Content-Type" => "application/json" }) end - let(:env) do + let :env do Rack::MockRequest.env_for( - 'http://example.com:8080/oauth2callback?code=authcode&'\ - 'state=%7B%22current_uri%22%3A%22%2Ffoo%22%2C%22'\ - 'session_id%22%3A%22abc%22%7D', - 'REMOTE_ADDR' => '10.10.10.10' + "http://example.com:8080/oauth2callback?code=authcode&"\ + "state=%7B%22current_uri%22%3A%22%2Ffoo%22%2C%22"\ + "session_id%22%3A%22abc%22%7D", + "REMOTE_ADDR" => "10.10.10.10" ) end - let(:request) { Rack::Request.new(env) } + let(:request) { Rack::Request.new env } - before(:example) do - request.session['g-xsrf-token'] = 'abc' + before :example do + request.session["g-xsrf-token"] = "abc" end - it 'should return credentials when valid code present' do + it "should return credentials when valid code present" do expect(credentials).to be_instance_of( Google::Auth::UserRefreshCredentials ) end - it 'should return next URL to redirect to' do - expect(next_url).to eq '/foo' + it "should return next URL to redirect to" do + expect(next_url).to eq "/foo" end - it 'should fail if xrsf token in session and does not match request' do - request.session['g-xsrf-token'] = '123' + it "should fail if xrsf token in session and does not match request" do + request.session["g-xsrf-token"] = "123" expect { credentials }.to raise_error(Signet::AuthorizationError) end end - describe '#handle_auth_callback' do - let(:result) { authorizer.handle_auth_callback('user1', request) } + describe "#handle_auth_callback" do + let(:result) { authorizer.handle_auth_callback "user1", request } let(:credentials) { result[0] } let(:next_url) { result[1] } - it_behaves_like 'handles callback' + it_behaves_like "handles callback" end - describe '#handle_auth_callback_deferred and #get_credentials' do - let(:next_url) do - Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) + describe "#handle_auth_callback_deferred and #get_credentials" do + let :next_url do + Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred request end - let(:credentials) do + let :credentials do next_url - authorizer.get_credentials('user1', request) + authorizer.get_credentials "user1", request end - it_behaves_like 'handles callback' + it_behaves_like "handles callback" end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 50ced66..cd90e23 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -27,17 +27,17 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -spec_dir = File.expand_path(File.dirname(__FILE__)) -root_dir = File.expand_path(File.join(spec_dir, '..')) -lib_dir = File.expand_path(File.join(root_dir, 'lib')) +spec_dir = __dir__ +root_dir = File.expand_path File.join(spec_dir, "..") +lib_dir = File.expand_path File.join(root_dir, "lib") -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.unshift(lib_dir) +$LOAD_PATH.unshift spec_dir +$LOAD_PATH.unshift lib_dir $LOAD_PATH.uniq! # set up coverage -require 'simplecov' -require 'coveralls' +require "simplecov" +require "coveralls" SimpleCov.formatters = [ Coveralls::SimpleCov::Formatter, @@ -45,18 +45,18 @@ SimpleCov.formatters = [ ] SimpleCov.start -require 'faraday' -require 'rspec' -require 'logging' -require 'rspec/logging_helper' -require 'webmock/rspec' -require 'multi_json' +require "faraday" +require "rspec" +require "logging" +require "rspec/logging_helper" +require "webmock/rspec" +require "multi_json" # Preload adapter to work around Rubinius error with FakeFS -MultiJson.use(:json_gem) +MultiJson.use :json_gem # Allow Faraday to support test stubs -Faraday::Adapter.load_middleware(:test) +Faraday::Adapter.load_middleware :test # Configure RSpec to capture log messages for each test. The output from the # logs will be stored in the @log_output variable. It is a StringIO instance. @@ -78,15 +78,15 @@ class DummyTokenStore @tokens = {} end - def load(id) + def load id @tokens[id] end - def store(id, token) + def store id, token @tokens[id] = token end - def delete(id) - @tokens.delete(id) + def delete id + @tokens.delete id end end